tags:

views:

78

answers:

1

I want to use swig for generation of read-only wrappers for a complex object. The object which I want to wrap will always be existent while I will read it. And also I will only use my wrappers at the time that object is existent, thus I don't need any memory management from SWIG.

For following swig interface:

%module test

%immutable;
%inline

%{
    struct Foo
    {
        int a;
    };

    struct Bar
    {
        int b;
        Foo f;
    };
%}

I will have a wrappers which will have a lot of garbage in generated interfaces and do useless work which will reduce performance in my case.
Generated java wrapper for Bar class will be like this:

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);
  }

}

I don't need 'swigCMemOwn' field in my wrapper since it always will be false. All code related to this field will also be useless.

There are also unnecessary logic in native code:

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;
}

I don't need these calls to malloc and memmove.

I want to force swig to resolve both of these problems, but don't know how. Is it possible?

+1  A: 

To do this, it's necessary to write a custom typemaps for structure types, like this one:

%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;
Dmitriy Matveev