J'ai une interface C qui ressemble à ceci (simplifié):C à Python via SWIG: ne peut pas obtenir les paramètres ** vides pour maintenir leur valeur
extern bool Operation(void ** ppData);
extern float GetFieldValue(void* pData);
extern void Cleanup(p);
qui est utilisé comme suit:
void * p = NULL;
float theAnswer = 0.0f;
if (Operation(&p))
{
theAnswer = GetFieldValue(p);
Cleanup(p);
}
Vous remarquerez que Operation() alloue le tampon p, que GetFieldValue interroge p, et que Cleanup libère p. Je n'ai aucun contrôle sur l'interface C - ce code est largement utilisé ailleurs. Je voudrais appeler ce code à partir de Python via SWIG, mais j'ai été incapable de trouver de bons exemples de la façon de passer un pointeur sur un pointeur - et de récupérer sa valeur.
Je pense que la bonne façon de le faire est par l'utilisation de typemaps, donc je défini une interface qui serait automatiquement déréférencer p pour moi du côté C:
%typemap(in) void** {
$1 = (void**)&($input);
}
Cependant, je ne pouvais pas obtenir le suivant le code python pour travailler:
import test
p = None
theAnswer = 0.0f
if test.Operation(p):
theAnswer = test.GetFieldValue(p)
test.Cleanup(p)
Après avoir appelé test.Operation(), p a toujours gardé sa valeur initiale de None.
Toute aide pour trouver la bonne façon de le faire dans SWIG serait très appréciée. Sinon, il est probable que j'écrirai simplement un wrapper C++ autour du code C qui empêchera Python de gérer le pointeur. Et puis enveloppez ce wrapper avec SWIG. Quelqu'un m'arrête!
Edit:
Merci à Jorenko, j'ai maintenant l'interface SWIG suivante:
% module Test
%typemap (in,numinputs=0) void** (void *temp)
{
$1 = &temp;
}
%typemap (argout) void**
{
PyObject *obj = PyCObject_FromVoidPtr(*$1, Cleanup);
$result = PyTuple_Pack(2, $result, obj);
}
%{
extern bool Operation(void ** ppData);
extern float GetFieldValue(void *p);
extern void Cleanup(void *p);
%}
%inline
%{
float gfv(void *p){ return GetFieldValue(p);}
%}
%typemap (in) void*
{
if (PyCObject_Check($input))
{
$1 = PyCObject_AsVoidPtr($input);
}
}
Le code python qui utilise cette interface SWIG est la suivante:
import test
success, p = test.Operation()
if success:
f = test.GetFieldValue(p) # This doesn't work
f = test.gvp(p) # This works!
test.Cleanup(p)
Bizarrement, Dans le code python, test.GetFieldValue (p) renvoie gibberish, mais test.gfv (p) renvoie la valeur correcte. J'ai inséré du code de débogage dans le typemap pour void *, et les deux ont la même valeur de p! L'appel Des idées à ce sujet?
Mise à jour: J'ai décidé d'utiliser ctypes. Beaucoup plus facile.
1. 'p' est en même temps 'vide **' et 'void *' dans votre code Python 2. 'None' est immuable donc' p' (un objet auquel il fait référence) ne changera pas quoi que ce soit (bien que vous puissiez lier 'p' à un objet différent (en utilisant' = ')). – jfs