2010-09-07 112 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; 
} 
情況