我想从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.i
(http://docs.scipy.org/doc/numpy/reference/swig.interface-file.html),则不需要手动编写类型映射表,它已经将必要的类型映射把C转换成NumPy数组,反之亦然。
在你的情况(假设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