SWIG C-to-Python Int Array

时间:2011-04-25 12:53:15

标签: python c linux swig

我正在尝试使用swig:#/ p>从python中使用以下原型访问C函数

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

Swig创建.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

定义

3 个答案:

答案 0 :(得分:14)

如果可以,请使用ctypes。它更简单。但是,既然你要求SWIG,你需要的是一个描述如何处理int *的类型映射。 SWIG不知道可以指出多少个整数。以下内容来自multi-argument typemaps上的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参数。

P.S。如果需要,我可以发布一个完整的工作示例(适用于Windows)。

答案 1 :(得分:8)

马克是对的,你需要一个打字机。但是,如果使用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中的这2个参数融合到单个python数组参数中,无需单独传递数组长度。您的电话将如下所示:

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

答案 2 :(得分:2)

你需要构建一个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