2012-07-10 58 views
0

我在C頭文件中的下列函數的構造函數:痛飲,巨蟒,C與void返回參數

int my_fun(int i, void *a, void *b, void *c); 

,以提供一些背景,我提供一個C代碼實現,說明它如何可能使用:

int error; 
double *a, *b, *c; 

int i = 1; 
int num = 500; 
int num_dim = 2; 

a = (double *) calloc(num, sizeof(double)); 
b = (double *) calloc(num, sizeof(double)); 
if (num_dim >= 3) 
    c = (double *) calloc(num, sizeof(double)); 
else 
    c = 0 

error = my_fun(i,a,b,c); 
error = my_fun(i,NULL,b,NULL); /*read only b*/ 

我想知道如何在SWIG接口文件中實現這個。我已使用typemaps.i作爲其他類型的指針返回參數,但它似乎不支持void*

回答

3

SWIG提供的文件carrays.icalloc匹配良好。您可以使用宏%array_functions%array_class來公開一些將C風格數組包裝爲目標語言的幫助器函數。 (即使你使用C,你仍然可以使用它們)。我做了以下接口封裝,並與%include定義了一個簡單my_fun一下子:

%module test 

%include "carrays.i" 

%array_functions(double,DoubleArray) 

%inline %{ 
    int my_fun(int i, void *a, void *b, void *c) { 
    printf("my_fun: i=%d, a=%p, b=%p, c=%p\n",i,a,b,c); 
    return 0; 
    } 
%} 

如果你想支持更多類型的不僅僅是calloc(num, sizeof(double))你需要添加更多%array_functions到您的接口文件。 carrays.i還生成功能,讓和數組中設置特定值,以及刪除它們

之後,你的例子使用成爲在Python如下:

import test 

i = 5 
num = 500 
num_dim = 2 

a = test.new_DoubleArray(num) 
b = test.new_DoubleArray(num) 
c = None 
if num_dim >= 3: 
    c = test.new_DoubleArray(num) 

error = test.my_fun(i,a,b,c) 
error = test.my_fun(i,None,b,None) 

# Beware of the exceptions, you need a finally: really 
test.delete_DoubleArray(a) 
test.delete_DoubleArray(b) 
test.delete_DoubleArray(c) 

我編譯和運行此我的系統上搭配:

 
swig -python -Wall test.i 
gcc -fPIC -I/usr/include/python2.7 test_wrap.c -shared -o _test.so -Wall -Wextra 
LD_LIBRARY_PATH=. python2.7 run.py 

這給了以下的輸出:

 
my_fun: i=5, a=0x2767fa0, b=0x2768f50, c=(nil) 
my_fun: i=5, a=(nil), b=0x2768f50, c=(nil) 

由於這裏的「數組」只是代理C中使用calloc分配的實際內存塊,所以您對該數組所做的任何更改都會在您下次讀取時從Python中看到。


如果您使用的%array_class代替%array_functions的Python代碼變成:這裏的引用計數已刪除的需要

import test 

i = 5 
num = 500 
num_dim = 2 

a = test.DoubleArray(num) 
b = test.DoubleArray(num) 
c = None 
if num_dim >= 3: 
    c = test.DoubleArray(num) 

error = test.my_fun(i,a.cast(),b.cast(),c.cast() if c else None) 
error = test.my_fun(i,None,b.cast(),None) 

通知明確刪除的磁盤陣列,解決與例外的問題,通過推遲至參考計數。 %array_class還提供了__getitem____setitem__的實現,因此它可以像Python中的任何其他數組或容器那樣進行子腳本化。 (雖然沒有界限,就像C一樣)