2011-12-15 42 views
1

我想知道为了处理getFoo需要什么SWIG接口文件的变化返回一个指向一个自定义结构数组的指针(sender_id_t)。没有任何特殊的SWIG接口代码,我只能得到Java方面的指针。我怎样才能把这个指针变成我可以循环或迭代的东西(在Java中),这样我就可以得到每个sender_id_t的id值?感谢任何建议。使用SWIG来处理C函数返回一个指向Java中结构数组的指针

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': 

回答

2

最简单的解决这个不涉及编写任何JNI的话 - 实际上它是method 2。所以我所做的就是使用carrays.i来公开一个非常基本的接口,然后编写一小段Java以使其视图更加可用/直观。关键是你需要提供一种将数组的知识结合在一起的方式。我已经组建了一个最小的完整示例来说明,它返回一个Java数组,但它同样适用于ArrayList或任何您喜欢的集合。

首先一个头文件,与紧凑内嵌实现:

%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()并使其和:

#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 

这然后用包相应的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宏生成的函数。

+0

感谢这样一个完整的例子。我能够很好地编译你的示例代码。当我尝试使用我的结构(sender_id_t_)时,遇到了将sizeof应用于sender_id_t_.id属性的问题。我在上面的问题中粘贴了编译错误。有任何想法吗? – c12 2011-12-19 03:03:17