Горячий способ избавиться от выделения / освобождения памяти в оболочках Swig? - PullRequest
0 голосов
/ 06 мая 2010

Я хочу использовать swig для создания оболочек только для чтения для сложного объекта. Объект, который я хочу обернуть, всегда будет существовать, пока я буду его читать. Кроме того, я буду использовать свои оболочки только в тот момент, когда объект существует, поэтому мне не нужно никакого управления памятью из SWIG.

Для следующего интерфейса Swig:

%module test

%immutable;
%inline

%{
    struct Foo
    {
        int a;
    };

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

У меня будет обертка, которая будет содержать много мусора в сгенерированных интерфейсах и выполнит бесполезную работу, которая снизит производительность в моем случае.
Сгенерированная Java-оболочка для класса Bar будет выглядеть так:

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 Ответ

2 голосов
/ 07 мая 2010

Для этого необходимо написать пользовательские карты типов для структурных типов, например:

%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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...