python的swig typemap:输入和输出数组

时间:2010-09-07 15:50:23

标签: python c swig

我想在Python中使用C函数:

extern int convertAtoB( stateStruct *myStruct,
                        const double PointA[3],
                        double PointB[3]);

使用SWIG,我想我需要定义一个类型映射来转换两个点(PointA是输入,PointB是输出),以便Python可以使用它。在typemaps.i中似乎没有与此一起使用的类型映射,因此我必须定义一个。我似乎无法在SWIG文档中找到数组的示例。

我想像这样使用这个库:

s = externalStruct()
point_a = [1, 2, 3]
result, point_b = convertAtoB(s, point_a)
print point_b
"expect [4, 5, 6]"

我该怎么做?感谢

3 个答案:

答案 0 :(得分:3)

你快到了。要删除python签名中的伪参数,您需要将%typemap(in)的{​​{1}}更改为PointB[3],以指示SWIG忽略该输入值(您已经获取了它的副本无论如何)。这将从python方法签名中删除伪参数。

但是,我不确定是否需要复制整个%typemap(in,numinputs=0)以进行该专业化。可能有一种方法可以重用实际的类型映射,但我不知道如何。否则你最终会得到一个额外的

%typemap(in)

答案 1 :(得分:1)

这是我找到的一个解决方案,但它可能不是最好的:

%typemap(in) double[ANY] (double temp[$1_dim0]) {
  int i;
  if (!PySequence_Check($input)) {
    PyErr_SetString(PyExc_ValueError,"Expected a sequence");
    return NULL;
  }
  if (PySequence_Length($input) != $1_dim0) {
    PyErr_SetString(PyExc_ValueError,"Size mismatch. Expected $1_dim0 elements");
    return NULL;
  }
  for (i = 0; i < $1_dim0; i++) {
    PyObject *o = PySequence_GetItem($input,i);
    if (PyNumber_Check(o)) {
      temp[i] = (double) PyFloat_AsDouble(o);
    } else {
      PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers");      
      return NULL;
    }
  }
  $1 = temp;
}

这是我最终遇到的将Python列表转换为数组的文档中的一个示例。下一部分更难,拼凑几个例子,我可以将返回数组转换为python列表:

%typemap(argout) double PointB[3]{
    PyObject *o = PyList_New(3);
    int i;
    for(i=0; i<3; i++)
    {
        PyList_SetItem(o, i, PyFloat_FromDouble($1[i]));
    }
    $result = o;
}

但是,我必须为API中的每个返回值创建其中一个。此外,我必须使用虚拟值作为参数调用它:

point_b = convertAtoB(s, point_a, dummy)

有更好的方法吗?

答案 2 :(得分:1)

这是一个旧帖子,但我回答了,因为关于SWIG没有回复这么多帖子。

具体针对上述情况

%typemap(in, numinputs=0) double PointB[3] {
  double tmp[3];
  $1 = tmp;
}

%typemap(argout) double PointB[3] {
  PyObject *o = PyList_New(3);
  int i;
  for(i=0; i<3; i++)
  {
    PyList_SetItem(o, i, PyFloat_FromDouble($1[i]));
  }
  $result = o;
}