在swig包装器中摆脱内存分配/解除分配的热点?

时间:2010-05-06 03:52:01

标签: java swig

我想使用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解决这两个问题,但不知道如何解决。有可能吗?

1 个答案:

答案 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;