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 来说,正确设置描述符的细微之处可能是让这种“正常工作”开箱即用的主要障碍。