我正在试图找出需要哪些SWIG接口文件更改才能处理getFoo返回一个指向自定义结构数组的指针(sender_id_t)。没有任何特殊的SWIG接口代码,我只得到Java端的指针。如何将该指针转换为可循环或迭代的东西(在Java中),以便我可以获取每个sender_id_t id值?感谢任何建议。
C结构:
typedef unsigned char id_v1_t[32];
typedef id_v1_t id_t;
%rename (Sample) sender_id_t_;
struct sender_id_t_ {
id_t id;
uint32_t phy_idx;
};
C函数:
//This will return a pointer to an array of sender_id_t data. The number of elements is retrieved from a separate call.
sender_id_t* getFoo(resultset_t* resultset);
例外:
[exec] test_wrap.c: In function `new_foo_array':
[exec] test_wrap.c:785: error: invalid application of `sizeof' to incomplete type `sender_id_t_'
[exec] test_wrap.c: At top level:
[exec] test_wrap.c:792: error: return type is an incomplete type
[exec] test_wrap.c: In function `foo_array_getitem':
[exec] test_wrap.c:793: error: invalid use of undefined type `struct sender_id_t_'
[exec] test_wrap.c:793: error: dereferencing pointer to incomplete type
[exec] test_wrap.c:793: warning: `return' with a value, in function returning void
[exec] test_wrap.c: At top level:
[exec] test_wrap.c:795: error: parameter `value' has incomplete type
[exec] test_wrap.c: In function `foo_array_setitem':
答案 0 :(得分:2)
对此最简单的解决方案根本不涉及编写任何JNI - 实际上它是method 2。所以我所做的是使用carrays.i来展示一个非常基本的接口,然后编写一些Java来使public
视图更加可用/直观。关键是你需要提供一种方法,将数组和的知识集中在一起。我已经整理了一个最小的完整示例来说明,它返回一个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的示例更简洁 - 编写起来更简单,更难以引入错误,使其更易于维护。任何查看它的Java 或 C程序员都可以看到正在发生的事情。在性能方面可能没那么糟糕,并且可能不会在一些关键路径上花费大量时间 - 如果基准测试显示它是一个问题,那么以后它仍然很容易沿着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
宏生成的所有函数。