2011-11-13 67 views
6

我有內部header.h,看起來像定義的結構:痛飲/ Python的數組內結構

typedef struct { 
.... 
    int  icntl[40]; 
    double cntl[15]; 
    int  *irn, *jcn; 
.... 

當我初始化這個結構的對象,我有機會到整數/雙打,但不是數組。

>> st.icntl 
<Swig Object of type 'int *' at 0x103ce37e0> 
>> st.icntl[0] 
Traceback (most recent call last): 
    File "test_mumps.py", line 19, in <module> 
    print s.icntl[0] 
TypeError: 'SwigPyObject' object is not subscriptable 

如何訪問讀/寫中的值?

回答

6

最簡單的方法是將您的陣列包裝在struct內,然後可以提供extra methods to meet the "subscriptable" requirements

我已經放在一個小例子。它假定你使用的是C++,但是相應的C版本由此構建起來相當簡單,只需要一點點重複。

首先亮相,在C++頭有我們想要包裹struct和我們用來包裹固定大小的數組模板:

template <typename Type, size_t N> 
struct wrapped_array { 
    Type data[N]; 
}; 

typedef struct { 
    wrapped_array<int, 40> icntl; 
    wrapped_array<double, 15> cntl; 
    int  *irn, *jcn; 
} Test; 

我們相應痛飲接口,則看起來像:

%module test 

%{ 
#include "test.h" 
#include <exception> 
%} 

%include "test.h" 
%include "std_except.i" 

%extend wrapped_array { 
    inline size_t __len__() const { return N; } 

    inline const Type& __getitem__(size_t i) const throw(std::out_of_range) { 
    if (i >= N || i < 0) 
     throw std::out_of_range("out of bounds access"); 
    return self->data[i]; 
    } 

    inline void __setitem__(size_t i, const Type& v) throw(std::out_of_range) { 
    if (i >= N || i < 0) 
     throw std::out_of_range("out of bounds access"); 
    self->data[i] = v; 
    } 
} 

%template (intArray40) wrapped_array<int, 40>; 
%template (doubleArray15) wrapped_array<double, 15>; 

訣竅是我們用%extend來提供__getitem__這是Python用於下標讀取和__setitem__寫入。 (我們也可以提供一個__iter__來使類型可迭代)。我們還給出了具體的wraped_array,我們希望使用唯一的名稱使SWIG將它們包裝在輸出中。

使用隨機提供的接口,我們現在可以做的:

>>> import test 
>>> foo = test.Test() 
>>> foo.icntl[30] = -654321 
>>> print foo.icntl[30] 
-654321 
>>> print foo.icntl[40] 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "test.py", line 108, in __getitem__ 
    def __getitem__(self, *args): return _test.intArray40___getitem__(self, *args) 
IndexError: out of bounds access 

您也可能會發現this approach有用/有趣的選擇。

3

我會在Python這樣做

ptr = int(st.icntl) 
import ctypes 
icntl = ctypes.c_int * 40 
icntl = icntl.from_address(ptr) 

print icntl[0] 
icntl[0] = 1 
for i in icntl: 
    print i