2013-01-03 35 views
1

我正在爲我編寫的科學C庫創建python包裝。該庫包含雙打的恆定數組在編譯時全局定義,即使用SWIG的模塊級numpy陣列

const double arr[NARR] = { 200.0, 201.0, ... 899.0, 900.0 }; 

我想用SWIG使這個模塊級numpy的陣列在我的Python模塊,即

>>> import foo 
>>> foo.arr 
array([200.0, 201.0, ..., 889.9, 900.0]) 

我似乎無法找到文檔中的任何東西來做一個常數數組。一切似乎都是從函數返回numpy數組,或者定義非數組常量。

我知道如何通過手動纏繞陣列要做到這一點:

npy_intp dim[1] = { NARR }; 
PyObject *a = PyArray_SimpleNewFromData(1, dim, NPY_DOUBLE, arr); 
PyObject_SetAttrString(module, "arr", a); 

我不能讓它使用SWIG工作。當我嘗試將上面的代碼放在我的foo.i文件的init塊中時,「arr」變量不會顯示在foo模塊中。

任何人都可以告訴我如何讓這個工作正常嗎?

EDIT

用於包裹所述陣列改變的代碼示例手動基於從seberg的建議。

+0

不知道如何與痛飲(也許最簡單的辦法就是,返回它的功能),但改變陣列'data'結構成員相當做到這一點肯定是錯的。有'PyArray_SimpleFromData'或者這樣的... – seberg

+0

感謝您的提示!我已更正了示例以反映您的建議。如果必須手動包裝數組,我一定會使用這個函數。 – SethMMorton

+0

當你低調時,解釋爲什麼OP可以改善問題是有幫助的。 – SethMMorton

回答

1

我已經找到了解決這個問題的辦法,但是它非常黑客。

我在foo.i文件中包含了兩個代碼擴展名,一個在C中,另一個在python中。在C擴展創建返回C數組,以告訴SWIG來創建一個返回該C數組作爲numpy的數組的包裝聲明沿功能:

/* Tell SWIG I want the function to output a numpy array */ 
%apply double ARGOUT_ARRAY1[ANY] { double a[NARR] }; 
/* Create a function that returns a copy of the array */ 
%inline %{ 
void _get_arr(double a[NARR]) { 
    for (int i = 0; i < NARR; i++) 
     a[i] = arr[i]; 
} 
%} 

的Python擴展調用該函數並將其放入模塊級numpy的數組變量arr(我使它只讀良好的措施):

%pythoncode %{ 
# Make the arr array a read-only module-level numpy array 
arr = _get_arr() 
arr.flags.writeable = False 
%} 

因爲我要分發此作爲,我可以控制在導入的功能__init__.py文件,因此不會使用foo導入。

我現在得到想要的結果:

>>> import foo 
>>> foo.arr 
array([200.0, 201.0, ..., 889.9, 900.0]) 
>>> foo.arr[0] = 10 
RuntimeError: array is not writeable 
>>> foo._get_arr() 
AttributeError: 'module' object has no attribute '_get_arr'