SWIG C到Python Int数组

我想从Python使用swig访问一个C函数,下面的原型:

int cosetCoding(int writtenDataIn, int newData, const int memoryCells, int *cellFailure, int failedCell); 

Swig创build.so没有问题,我可以导入到Python,但是当我尝试访问它与以下内容:

  cosetCoding.cosetCoding(10,11,8,[0,0,0,0,0,0,0,0],0) 

我得到以下回溯:

 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: in method 'cosetCoding', argument 4 of type 'int *' 

指针应该是一个int数组,大小由memoryCells定义

如果可以的话,使用ctypes。 这很简单。 但是,既然你问了SWIG,你需要的是一个描述如何处理int *的类型映射。 SWIG不知道可能指向多少个整数。 以下是在SWIG文档中有关多参数类型映射的示例 :

 %typemap(in) (const int memoryCells, int *cellFailure) { int i; if (!PyList_Check($input)) { PyErr_SetString(PyExc_ValueError, "Expecting a list"); return NULL; } $1 = PyList_Size($input); $2 = (int *) malloc(($1)*sizeof(int)); for (i = 0; i < $1; i++) { PyObject *s = PyList_GetItem($input,i); if (!PyInt_Check(s)) { free($2); PyErr_SetString(PyExc_ValueError, "List items must be integers"); return NULL; } $2[i] = PyInt_AsLong(s); } } %typemap(freearg) (const int memoryCells, int *cellFailure) { if ($2) free($2); } 

请注意,对于这个定义,当从Python中调用时,会留下memoryCells参数,只传递一个数组,例如[1,2,3,4]用于cellFailure 。 typemap将生成memoryCells参数。

PS我可以发布一个完整的工作示例(对于Windows),如果你想要的话。

马克是对的,你需要一个类型映射。 但是,如果使用numpy.ihttp://docs.scipy.org/doc/numpy/reference/swig.interface-file.html),则不需要手动编写类型映射表,它已经将必要的类型映射把C转换成NumPy数组,反之亦然&#x3002;

在你的情况(假设cellFailure是一个输入数组),你会想要使用

 %apply (int DIM1, int* IN_ARRAY1) {(int memoryCells, int *cellFailure)} 

注意(正如Mark已经指出的),这将C中的这两个参数方便地融合为单个python数组参数,不需要单独传递数组长度。 您的电话将如下所示:

 from numpy import asarray cosetCoding.cosetCoding(10,11,asarray([0,0,0,0,0,0,0,0]),0) 

你需要构造一个c_int数组来工作:

 arr = (ctypes.c_int * 8)(0, 0, 0, 0, 0, 0, 0, 0) cosetCoding.cosetCoding(10, 11, 8, arr, 0) 

更新添加更完整的示例。 我在Python 2.6下使用ctypes版本1.1.0; 也许我们做的事情略有不同?

也许传递ctypes.byref(arr)呢?

 cosetCoding.cosetCoding(10, 11, 8, ctypes.byref(arr), 0) 

以下是我测试的内容:

共享对象: cosetCoding.c

 #include <stdio.h> int cosetCoding(int writtenDataIn, int newData, const int memoryCells, int *cellFailure, int failedCell) { printf("cellFailure: %d %d\n", cellFailure[0], cellFailure[1]); } 

编译:

 % gcc -shared -fPIC -o cosetCoding.so cosetCoding.c 

Python脚本: test_coset.py

 import ctypes cosetCoding = ctypes.cdll.LoadLibrary('./cosetCoding.so') arr = (ctypes.c_int * 8)(1, 2, 3, 4, 5, 6, 7, 8) cosetCoding.cosetCoding(10, 11, 8, arr, 0) 

输出:

 % python test_coset.py cellFailure: 1 2