2011-11-13 13 views
6

el interior Tengo una estructura definida dentro header.h que parece:TRAGO estructura

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

Cuando init un objeto con esta estructura, no tengo acceso a números enteros/dobles, pero no matrices .

>> 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 

¿Cómo tener acceso a los valores en lectura/escritura?

Respuesta

6

La manera más fácil de hacerlo es envolver sus matrices dentro de un struct, que puede proporcionar extra methods to meet the "subscriptable" requirements.

He reunido un pequeño ejemplo. Supone que estás usando C++, pero la versión C equivalente es bastante trivial para construir a partir de esto, solo requiere un poco de repetición.

En primer lugar, la cabecera de C++ que tiene el struct queremos envolver y una plantilla que usamos para envolver las matrices de tamaño fijo:

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; 

Nuestra interfaz SWIG correspondiente a continuación, se ve algo como:

%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>; 

El truco es que hemos utilizado %extend para suministrar __getitem__ que es lo que Python usa para lecturas de subíndice y __setitem__ para las escrituras. (También podríamos haber suministrado un __iter__ para hacer que el tipo sea iterable). También le dimos a wraped_array s específicos que deseamos utilizar nombres únicos para que SWIG los envuelva en la salida.

Con la interfaz suministrado ahora podemos hacer:

>>> 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 

También puede encontrar this approach útil/interesante como alternativa.

3

yo hubiera hecho esto en 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 
Cuestiones relacionadas