2011-12-15 40 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