我已经编写了以下测试头文件来演示问题:
```
我已经编写了以下测试头文件来演示问题:
```
typedef struct { } obj_t;
const short *get_data(const obj_t *obj, int *data_len) {
(void)obj;
static short arr[] = {1,2,3,4,5};
*data_len = sizeof(arr)/sizeof(*arr);
return arr;
}
我将解释我写的模块文件,开头很标准:
%module test
%{
%}
然后我们为data_len
参数设置了一个类型映射。它不需要在Java端可见,因为长度将由数组知道,但是我们确实需要安排一些存储空间供指针指向,并确保它足够长,以便在将数组返回给Java时我们能够读取它。
%typemap(in,numinputs=0,noblock=1) int *data_len {
int temp_len;
$1 = &temp_len;
}
我们希望在Java端使用short[]
作为返回类型,因此需要让SWIG进行相应的转换:
%typemap(jstype) const short *get_data "short[]"
%typemap(jtype) const short *get_data "short[]"
在JNI端中,我们可以直接传递jshortArray
的返回值,无需构建代理类型:
%typemap(jni) const short *get_data "jshortArray"
%typemap(javaout) const short *get_data {
return $jnicall;
}
最后,我们创建了一个类型映射,它将创建一个新的数组,大小基于从函数返回的长度,并将返回的结果复制到Java数组中。如果需要,我们应该在这里
free()
真实结果数组,但在我的示例中,它是静态分配的,因此不需要被释放。
%typemap(out) const short *get_data {
$result = JCALL1(NewShortArray, jenv, temp_len);
JCALL4(SetShortArrayRegion, jenv, $result, 0, temp_len, $1);
// If the result was malloc()'d free it here
}
最后,我们使用刚刚编写的类型映射包含 SWIG 要进行包装的头文件:
%include "test.h"
我用以下方式进行了测试:
public class run {
public static void main(String argv[]) {
System.loadLibrary("test");
obj_t obj = new obj_t();
short[] result = test.get_data(obj);
for (int i = 0; i < result.length; ++i) {
System.out.println(result[i]);
}
}
}
这将产生:
1
2
3
4
5
作为参考,您可以包装:
void get_data(const obj_t *obj, short const **data, int *data_len);
即使您的函数有一种方法可以在不设置数组的情况下查询其大小,您也可以通过在Java端分配正确大小的数组来稍微包装它。为此,您需要在Java中编写一个中间函数来查询大小,设置调用,然后返回结果数组。这将允许您使用
GetShortArrayElements
/
ReleaseShortArrayElements
进行可能为0的复制调用。
这样做是可行的,因为Java中的数组基本上是通过引用传递的,例如:
public class ret {
public static void foo(int arr[]) {
arr[0] = -100;
}
public static void main(String argv[]) {
int arr[] = new int[10];
System.out.println(arr[0]);
foo(arr);
System.out.println(arr[0]);
}
}