我想使用swig为复杂对象生成只读包装器。我想要包装的对象将始终存在,而我将阅读它。此外,我只会在对象存在时使用我的包装器,因此我不需要SWIG的任何内存管理。
对于以下swig界面:
%module test
%immutable;
%inline
%{
struct Foo
{
int a;
};
struct Bar
{
int b;
Foo f;
};
%}
我将有一个包装器,它会在生成的接口中产生大量垃圾,并且无用的工作会降低我的性能。
为Bar类生成的java包装器将是这样的:
public class Bar {
private long swigCPtr;
protected boolean swigCMemOwn;
protected Bar(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(Bar obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
testJNI.delete_Bar(swigCPtr);
}
swigCPtr = 0;
}
}
public int getB() {
return testJNI.Bar_b_get(swigCPtr, this);
}
public Foo getF() {
return new Foo(testJNI.Bar_f_get(swigCPtr, this), true);
}
public Bar() {
this(testJNI.new_Bar(), true);
}
}
我的包装器中不需要'swigCMemOwn'字段,因为它总是错误的。与此字段相关的所有代码也将无用。
本机代码中也有不必要的逻辑:
SWIGEXPORT jlong JNICALL Java_some_testJNI_Bar_1f_1get(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
jlong jresult = 0 ;
struct Bar *arg1 = (struct Bar *) 0 ;
Foo result;
(void)jenv;
(void)jcls;
(void)jarg1_;
arg1 = *(struct Bar **)&jarg1;
result = ((arg1)->f);
{
Foo * resultptr = (Foo *) malloc(sizeof(Foo));
memmove(resultptr, &result, sizeof(Foo));
*(Foo **)&jresult = resultptr;
}
return jresult;
}
我不需要对malloc和memmove进行这些调用。
我想强制swig解决这两个问题,但不知道如何解决。有可能吗?
答案 0 :(得分:2)
要做到这一点,有必要为结构类型编写自定义的类型图,如下所示:
%typemap(javabody) SWIGTYPE %{
private long swigCPtr;
protected $javaclassname(long cPtr) {
swigCPtr = cPtr;
}
%}
%typemap(jtype, nopgcpp="1") SWIGTYPE * "long"
%typemap(javaout) SWIGTYPE {
long cPtr = $jnicall;
return new $javaclassname(cPtr);
}
%typemap(javaout) SWIGTYPE *, SWIGTYPE [], SWIGTYPE (CLASS::*) {
long cPtr = $jnicall;
return (cPtr == 0) ? null : new $javaclassname(cPtr);
}
%typemap(out) SWIGTYPE %{
*($&1_ltype*)&$result = &$1;
%}
%typemap(javadestruct) SWIGTYPE ""
%typemap(javaclassmodifiers) SWIGTYPE "public final class"
%nodefaultctor;
%nodefaultdtor;
%immutable;