将shared_ptr与SWIG Directors for Java一起使用

Kek*_*koa 8 swig

我开始掌握SWIG,SWIG的最新版本(v3.0)似乎可以处理我开箱即用的所有内容,包括C++ 11的功能,但是我遇到了麻烦来使用shared_ptr和我的导演课程.

我能够shared_ptr很好地使用普通的代理类,但现在我的导演似乎不支持开箱即用.它给了我自动生成的类型SWIGTYPE_p_std__shared_ptrT_MyDataType_t,并且生成一个破坏的接口,因为它没有使用代理类使用的相同类型.

我有一个简单的例子,我正在尝试做什么(swig -c++ -java Test.i在swig 3.0上运行):

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() {};
};
Run Code Online (Sandbox Code Playgroud)

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

似乎我可以通过更改SWIGTYPE_p_std__shared_ptrT_MyDataType_tMyDataType任何地方的类型手动修复文件,但我希望有更多swig知识的人可以回答这个问题,这样就可以正确生成.

最好的线索,我是在这里,但我仍然试图找出如何正确使用这些类型的地图,特别是对shared_ptr不基本原语.

更新:

文件:

注意:目前不支持%shared_ptr和导演功能.

虽然它没有说明原因.如果有充分理由不在董事中使用shared_ptr,我想知道这对于swig director是不可能的.看起来使用你在其他地方使用的相同类型是有意义的.我希望答案是它仍然有可能.

Fle*_*exo 6

最新版本的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";
}
%}
Run Code Online (Sandbox Code Playgroud)

即使您只在示例中使用了directorout case,仍然需要directorin typemap使director_connect中的查找成功,因为它取决于具有正确的描述符.

这四个类型映射与函数中的in,javain和javaout类型映射等效,但由于它们在控制器中的作用而被逆转.

它们不够完整,无法处理所有情况,但它们在您的示例中起作用.该$typemap描述符内部调用需要一个版本痛饮3比包含在Ubuntu 14.04的一个新的-形式我写的我是从主干签出测试的唯一版本.您可以手动编写描述符(这只是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);
  }
}
Run Code Online (Sandbox Code Playgroud)

编译并运行它:

~/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
Run Code Online (Sandbox Code Playgroud)

哪个跑的时候给了:

In Java: 123
In C++: 123
Run Code Online (Sandbox Code Playgroud)

我想在Java的情况下 shared_ptr +导演的使描述符正确的微妙之处可能是让这个"正常工作"开箱即用的主要障碍.