如何使用Swig将数组(java中的long数组)从Java传递到C ++

我有样本.h文件,如下所示:

class Test { public: void SelectValues(long long values[]) }; 

我使用SWIG并从.i文件下面创建了JNI接口

 %module MyLib %include "carrays.i" %array_functions(long long, long_long_array ) %{ #include "Test.h" %} /* Let's just grab the original header file here */ %include  /*This line is used for calling conventions*/ % include "Test.h" 

当我创建Java方法时,它创建如下:

 public void SelectValues(SWIGTYPE_p_long_long includeKeys) 

同样对于JNI文件,它将参数作为jlongArray但仅使用简单的jlong 。 由于这个问题,我无法像long[]={1L,2L}那样创建长数组,并将其传递给Java方法以上以调用适当的JNI方法。

我希望SWIG以这样一种方式生成接口,我可以将上面提到的数组传递给我的C ++方法。

我已经阅读了这个问题 ,但它没有帮助我看到如何将数组从Java传递给C ++。

你在这里使用array_functions做的是正确和可用的,但是它专注于直接包装C ++代码,并且它不会使用底层Java数组。 您可以使用以下内容:

 SWIGTYPE_p_long_long array = MyLib.new_long_long_array(100); // new array with 100 elements. for (int i = 0; i < 100; ++i) { long_long_array_setitem(array, i, i); } new Test().SelectValues(array); 

其中array只是一个“真正的”C ++内存块的代理,您可以在Java端读取/写入并传递给包装函数。

我猜你的问题是你有兴趣让这种感觉在Java方面更“自然”。 SWIG还提供了array_class ,它类似地包装数组,但是作为一个正确的对象而不是静态函数的集合。 例如,如果您将接口文件更改为使用array_class(long long, LongLongArray)而不是array_functions ,则可以执行以下操作:

 LongLongArray array = new LongLongArray(100); for (int i = 0; i < 100; ++i) { array.setitem(i,i); } new Test().SelectValues(array.cast()); 

实际上,如果你愿意,你可以使用一些类型图使SWIG做更多的事情。 你的示例类在SelectValues中没有花费一个长度,所以我假设你是0终止数组,尽管你可以通过几个简单的更改同样很好地传递长度。

(为方便起见,我将你的类%inline到减少文件数量并为测试添加了一个虚拟实现)

 %module MyLib %{ #include  %} %typemap(jtype) long long values[] "long[]" %typemap(jstype) long long values[] "long[]" %typemap(javain) long long values[] "$javainput" %typemap(jni) long long values[] "jlongArray" %typemap(in) long long values[] { jboolean isCopy; $1 = JCALL2(GetLongArrayElements, jenv, $input, &isCopy); } %inline %{ class Test { public: void SelectValues(long long values[]) { while (*values) { std::cout << *values++ << "\n"; } } }; %} 

这里我们说代理类SWIG生成它和它生成的JNI类将使用long[] ,即Java数组。 我们不需要在Java代理到Java JNI转换中执行任何操作,因此javain只是直接传递。 在JNI的C ++端,这是一个jlongArray ,我们也在另一个typemap中指定了它。

然后我们需要一个in typemap来安排从Clong方面的jlong​​Array到long long[]转换 - 对此有一个JNI调用,我们不关心它是来自JVM的副本还是我们最终使用的实际内存。 (您可能会关心是否要修改结果并将其显示在Java中,例如)

我测试了这个:

 public class run { public static void main(String[] argv) { System.loadLibrary("mylib"); long arr[] = {100,99,1,0}; // Terminate with 0! new Test().SelectValues(arr); } } 

完全按照你的意愿行事。