Swig typemap java对象

时间:2014-09-30 00:26:56

标签: java swig

我正在尝试通过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:无法应用(对象)。没有定义任何类型图。我不知道如何为此制作打字机。有什么想法吗?

2 个答案:

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

输出显示someObjectsameObject指向同一个对象,例如:

java.lang.Object@7aa06577
java.lang.Object@7aa06577