最简单的解决方案根本不涉及编写任何 JNI - 实际上它是method 2。所以我所做的是使用卡瑞斯.i公开一个非常基本的接口,然后编写一点 Java 来制作public
认为它更有用/直观。关键是你需要提供一种将数组知识汇集在一起的方法and它的长度。我整理了一个最小的完整示例来说明,它返回一个 Java 数组,但它同样可以用于ArrayList
或任何您喜欢的收藏。
首先是一个头文件,具有紧凑的内联实现:
#ifndef TEST_H
#define TEST_H
struct Foo {
int v;
};
inline static struct Foo *getFoo() {
static struct Foo r[] = {{0},{1},{2}};
return r;
}
inline static unsigned short numFoo() {
return 3;
}
#endif
然后用以下内容包裹:
%module test
%{
#include "test.h"
%}
%include <carrays.i>
%array_functions(struct Foo, foo_array);
%rename(getFooImpl) getFoo;
%javamethodmodifiers getFoo() "private";
%javamethodmodifiers numFoo() "private";
%include "test.h"
%pragma(java) modulecode=%{
public static Foo[] getFoo() {
final int num = numFoo();
Foo ret[] = new Foo[num];
Foo result = getFooImpl();
for (int i = 0; i < num; ++i) {
ret[i] = foo_array_getitem(result, i);
}
return ret;
}
%}
我们在哪里重命名getFoo()
从头文件中获取并使其与相应的numFoo()
private
,即实施细节。
使用这两个私有函数,我们可以编写一个真正的,public Foo[] getFoo()
,调用这两个函数,然后将结果复制到已知大小的实际数组中。
我对此进行了测试:
public class main {
public static void main(String[] argv) {
System.loadLibrary("test");
Foo[] foos = test.getFoo();
System.out.println(foos[2].getV());
}
}
在我看来,这个解决方案比相应的基于 JNI 的示例更干净 - 编写更简单,并且更难引入错误,这使得它更易于维护。任何JavaorC 程序员看到它就几乎可以明白发生了什么。就性能而言,它可能不会差太多,并且在某些关键路径上可能不会花费大量时间 - 如果基准测试显示这是一个问题,那么以后仍然很容易走上 JNI 道路。
为了完整地“制作它”private
“方面您可能还想做类似的事情:
%javamethodmodifiers foo_array_getitem "private";
%ignore foo_array_setitem;
%ignore delete_foo_array;
%ignore new_foo_array;
%include <carrays.i>
%array_functions(struct Foo, foo_array);
隐藏由生成的所有函数%array_functions
macro.