【问题标题】:Using shared_ptr with SWIG Directors for Java将 shared_ptr 与 SWIG Director for Java 一起使用
【发布时间】:2014-04-28 05:53:55
【问题描述】:

我开始掌握 SWIG 的窍门,SWIG 的最新版本 (v3.0) 似乎可以处理我开箱即用所需的一切,包括 C++11 功能,但我已经达到了在我的导演类中使用 shared_ptr 时遇到问题。

我已经能够让shared_ptr 很好地与普通代理类一起工作,但现在在我的导演身上,它似乎不受开箱即用的支持。它给了我像SWIGTYPE_p_std__shared_ptrT_MyDataType_t 这样的自动生成类型,并且正在生成一个损坏的接口,因为它没有使用代理类使用的相同类型。

我有一个我正在尝试做的简化示例(在 swig 3.0 上使用 swig -c++ -java Test.i 运行):

Test.i

%module(directors="1") test
%{

%}

%include <std_shared_ptr.i>

%shared_ptr(MyDataType)

class MyDataType {
public:
    int value;
};

class NonDirectorClass {
public:
    std::shared_ptr<MyDataType> TestMethod();
};

%feature("director") CallbackBaseClass;

class CallbackBaseClass {
public:
    virtual ~CallbackBaseClass() {};
    virtual std::shared_ptr<MyDataType> GetDataFromJava() {};
};

基本上我要做的是在 Java 中扩展 CallbackBaseClass,我希望能够传递我的 shared_ptr 包装类型。非导演类生成 shared_ptr 类型就好了。正确生成了 director 类代理文件,但包装器中的 SwigDirector_ 方法引用了不正确的类型。

似乎我可以通过将SWIGTYPE_p_std__shared_ptrT_MyDataType_t的类型更改为MyDataType来手动修复文件,但我希望有更多知识的人可以回答这个问题,以便正确生成。

我得到的最好的线索是here,但我仍在试图弄清楚如何正确使用这些类型映射,尤其是对于shared_ptr 而不是基本原语。

更新:

文档says

注意:目前不支持 %shared_ptr 和 director 功能。

虽然它没有说明原因。我想知道这对于 swig 导演是否不可能,是否有充分的理由不在导演中使用 shared_ptr。使用与其他地方相同的类型似乎很有意义。我希望答案仍然是可能的。

【问题讨论】:

    标签: swig


    【解决方案1】:

    SWIG 文档的最新版本现在为:

    “对%shared_ptr 的支持有些有限,导演功能和成功程度因目标语言而异。请通过提供改进的补丁来帮助改进这种支持。”

    为了使您的示例正常工作,我们似乎需要添加四个缺失的类型映射,directorin、directorout、javadirectorin 和 javadirectorout:

    %module(directors="1") test
    
    %include <std_shared_ptr.i>
    
    %{
    #include <memory>
    #include <iostream>
    %}
    
    %shared_ptr(MyDataType)
    
    %feature("director") CallbackBaseClass;
    
    %typemap(javadirectorin) std::shared_ptr<MyDataType> "new $typemap(jstype, MyDataType)($1,true)";
    %typemap(directorin,descriptor="L$typemap(jstype, MyDataType);") std::shared_ptr<MyDataType> %{
      *($&1_type*)&j$1 = new $1_type($1);
    %}
    
    %typemap(javadirectorout) std::shared_ptr<MyDataType> "$typemap(jstype, MyDataType).getCPtr($javacall)";
    %typemap(directorout) std::shared_ptr<MyDataType> %{
      $&1_type tmp = NULL;
      *($&1_type*)&tmp = *($&1_type*)&$input;
      if (!tmp) {
        SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Attempt to dereference null $1_type");
        return NULL;
      }
      $result = *tmp;
    %}
    
    %inline %{
    class MyDataType {
    public:
        int value;
    };
    
    class NonDirectorClass {
    public:
        std::shared_ptr<MyDataType> TestMethod() { return std::make_shared<MyDataType>(); }
    };
    
    class CallbackBaseClass {
    public:
        virtual ~CallbackBaseClass() {};
        virtual std::shared_ptr<MyDataType> GetDataFromJava() = 0;
    };
    
    void frobinate(CallbackBaseClass& cb) {
        std::cout << "In C++: " << cb.GetDataFromJava()->value << "\n";
    }
    %}
    

    即使您在示例中只使用了directorout 的情况,但directorin 类型映射仍然需要在director_connect 中进行查找,因为它依赖于具有正确的描述符。

    这四个类型映射在功能上等同于 in、javain 和 javaout 类型映射,但由于它们在导向器中的作用而颠倒过来。

    它们不足以处理所有情况,但它们在您的示例中有效。描述符中的 $typemap 调用需要比 Ubuntu 14.04 中包含的版本更新的 SWIG 3 版本 - 在我编写的形式中,我测试过的唯一版本是从主干中检出的。您可以手动编写描述符(即descriptor="LMyDataType;"),但显然这不太通用。如上所述编写它的优点是它也可以正确处理%rename 指令。这也不能正确处理包,所以在这种情况下你也必须再次手动编写它。

    我能够测试并运行该示例,我添加了以下 run.java:

    public class run extends CallbackBaseClass {
      public MyDataType GetDataFromJava() {
        MyDataType val = new MyDataType();
        val.setValue(123);
        return val;
      }
    
      public static void main(String[] argv) {
        System.loadLibrary("test");
        run r = new run();
    
        System.out.println("In Java: " + r.GetDataFromJava().getValue());
        test.frobinate(r);
      }
    }
    

    并编译并运行它:

    ~/swig-trunk/preinst-swig -Wall -c++ -java  test.i  
    clang++-3.6 -stdlib=libc++ -Wall -Wextra -std=c++1y test_wrap.cxx -o libtest.so -I/usr/lib/jvm/default-java/include/ -I/usr/lib/jvm/default-java/include/linux -shared -fPIC 
    javac run.java
    LD_LIBRARY_PATH=. java run
    

    运行时给出的结果:

    In Java: 123
    In C++: 123
    

    我猜想对于带有shared_ptr+directors 的 Java 来说,正确设置描述符的细微之处可能是让这种“正常工作”开箱即用的主要障碍。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-21
      相关资源
      最近更新 更多