我正在尝试通过swig为这两个c ++函数生成java绑定
C ++函数
void SetUserData(void* data);
void* GetUserData() const;
在java方面,我希望它看起来像这样
setUserData(Object object);
getUserData() //return java.lang.Object
我希望void *指针指向我传递给它的任何java对象。在我的swig文件中,我尝试添加这些行
//swig file
%typemap(jstype) void* "java.lang.Object";
%apply Object {void*};
我收到编译错误: b2Fixture.swig(22):警告453:无法应用(对象)。没有定义任何类型图。我不知道如何为此制作打字机。有什么想法吗?
答案 0 :(得分:3)
您可能想要这样做:
%apply jobject { void* };
因为%apply将在一个C ++类型上定义的类型映射复制到另一个C ++类型。 Object
是Java类型,而不是C ++类型,因此没有要复制的任何类型映射。另一方面,jobject
是JNI的等价物。
另外假设你想要'正常'的GC语义(即不需要保留你传入的任何数据),你需要做更多的工作,例如:
%module test
%{
#include "test.hh"
%}
%apply jobject { void * };
%typemap(in) void * {
void *old = getData();
if (old) JCALL1(DeleteGlobalRef, jenv, (jobject)old);
$1 = JCALL1(NewGlobalRef, jenv, $input);
}
%typemap(out) void * {
$result = (jobject)($1);
}
%include "test.hh"
这为您的数据创建了一个新的全局参考,这可能是唯一阻止它被GC释放的东西。
给定一个头文件:
void setData(void *);
void *getData();
和实施:
#include "test.hh"
namespace {
void *d = nullptr;
}
void setData(void *d) {
::d = d;
}
void *getData() {
return d;
}
这足以允许:
public class run {
public static void main(String[] argv) {
System.loadLibrary("test");
Object example = "HELLO";
test.setData(example);
System.out.println(test.getData());
}
}
正常工作。
正如所写,这些类型地图非常难看 - 它们会影响{em>所有对void *
的使用。因此,如果你真的使用了这个,你会希望第二次使用%apply
或%clear
来限制它们的影响。您还可以在头文件中命名参数,并使用它来限制应用typemap的位置。
答案 1 :(得分:-1)
为了完整起见,这是另一种(更简单?)方法,用JavaCPP来完成。假设我们在C ++中有一个GlobalData.h
这样的文件:
class Data {
public:
JNIEnv* env;
jobject data;
Data(JNIEnv* env, jobject obj) : env(env), data(NULL) { }
~Data() { if (data != NULL) env->DeleteGlobalRef(data); }
void SetUserData(jobject obj) {
if (data != NULL) env->DeleteGlobalRef(data);
data = env->NewGlobalRef(obj);
}
jobject GetUserData() { return data; }
};
我们可以这样使用Java:
import org.bytedeco.javacpp.*;
import org.bytedeco.javacpp.annotation.*;
@Platform(include="GlobalData.h")
public class GlobalData {
static { Loader.load(); }
public static class Data extends Pointer {
public Data() { allocate(); }
private native @Raw(withEnv=true) void allocate();
public native void SetUserData(@Raw Object obj);
public native @Raw Object GetUserData();
}
public static void main(String[] args) {
Object someObject = new Object();
Data myData = new Data();
myData.SetUserData(someObject);
Object sameObject = myData.GetUserData();
System.out.println(someObject);
System.out.println(sameObject);
}
}
输出显示someObject
和sameObject
指向同一个对象,例如:
java.lang.Object@7aa06577
java.lang.Object@7aa06577