2010-09-07 117 views
4

我有一个C函数我想在Python的使用方法:使用痛饮为蟒蛇痛饮类型映射:输入和输出数组

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

,我想我需要定义一个类型映射到两个点转换(点A的输入,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]" 

我将如何做到这一点?由于

回答

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) 

有没有更好的方法?

3

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

但我不确定,但是,如果您需要复制整个%typemap(in)该专业化。可能有重用实际类型映射的方法,但我不知道如何。否则,你会拥有一个额外的

%typemap(in,numinputs=0) double PointB[3] (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; 
} 
1

这是一个古老的线程,但我回答这个问题,因为没有那么多的帖子已就痛饮有了答案。

特异性靶向以上

%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; 
} 
情况