2010-09-07 5 views
4

I ont une fonction C Je veux utiliser en Python:typemap rasade pour python: entrée et tableaux sortie

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

En utilisant SWIG, je pense que je dois définir un typemap pour convertir les deux points (Pointa la input, PointB la sortie) pour que Python puisse l'utiliser. Il ne semble pas y avoir de typemap dans typemaps.i qui fonctionne avec ceci, donc je dois en définir un. Je n'arrive pas à trouver des exemples de cela pour les tableaux dans la documentation SWIG.

Je voudrais utiliser cette bibliothèque comme ceci:

s = externalStruct() 
point_a = [1, 2, 3] 
result, point_b = convertAtoB(s, point_a) 
print point_b 
"expect [4, 5, 6]" 

Comment puis-je faire cela? Merci

Répondre

1

Voici une solution que je trouve, mais il pourrait ne pas être le meilleur:

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

Voici un exemple dans les documents que je suis tombé sur enfin qui convertissent en Python liste des tableaux. La partie suivante est plus difficile, assemblant plusieurs exemples que je pourrais convertir le tableau de retour dans une liste de 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; 
} 

Cependant, je dois créer un de ces pour chaque valeur de retour dans l'API. Aussi je dois l'appeler avec une valeur factice en tant que paramètre:

point_b = convertAtoB(s, point_a, dummy) 

Y at-il un meilleur moyen?

3

Vous y êtes presque. Pour se débarrasser de l'argument fictif dans la signature python, vous devez modifier %typemap(in) pour PointB[3] à %typemap(in,numinputs=0) pour indiquer à SWIG d'ignorer cette valeur d'entrée (vous en prenez déjà une copie de toute façon). Cela supprimera l'argument fictif de la signature de la méthode python. Je ne suis pas sûr cependant, si vous devez copier le %typemap(in) entier pour cette spécialisation. Probablement il y a un moyen de réutiliser le typemap réel, mais je ne sais pas comment. Sinon, vous vous retrouverez avec un

%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

supplémentaire Ceci est un vieux fil, mais je réponds parce que pas tant de poste a été répondu au sujet SWIG.

Pour cibler spécifiquement la situation ci-dessus

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