C para Python via SWIG: não é possível obter parâmetros ** nulos para manter seu valor
Eu tenho uma interface C com esta aparência (simplificada):
extern bool Operation(void ** ppData);
extern float GetFieldValue(void* pData);
extern void Cleanup(p);
que é usado da seguinte maneira:
void * p = NULL;
float theAnswer = 0.0f;
if (Operation(&p))
{
theAnswer = GetFieldValue(p);
Cleanup(p);
}
Você observará que Operation () aloca o buffer p, que GetFieldValue consulta p e que Cleanup libera p. Não tenho controle sobre a interface C - esse código é amplamente usado em outros lugare
Gostaria de chamar esse código do Python viaGOL, mas não consegui encontrar bons exemplos de como passar um ponteiro para outro - e recuperar seu valo
Acho que a maneira correta de fazer isso é usando mapas de tipo, por isso defini uma interface que desreferiria automaticamente p para mim no lado C:
%typemap(in) void** {
$1 = (void**)&($input);
}
No entanto, não foi possível obter o seguinte código python para funcionar:
import test
p = None
theAnswer = 0.0f
if test.Operation(p):
theAnswer = test.GetFieldValue(p)
test.Cleanup(p)
Após chamar test.Operation (), p sempre manteve seu valor inicial de None.
Qualquer ajuda para descobrir a maneira correta de fazer isso no SWIG seria muito apreciada. Caso contrário, provavelmente escreverei um wrapper C ++ em torno do código C que impede o Python de lidar com o ponteiro. E depois enroleaquel wrapper com SWIG. Alguém me pare
Editar
Graças a Jorenko, Agora tenho a seguinte interface SWIG:
% 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);
}
}
O código python que usa essa interface SWIG é o seguinte:
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)
Odly, no código python, test.GetFieldValue (p) retorna sem sentido, mas test.gfv (p) retorna o valor correto. Inseri o código de depuração no mapa de tipos para void * e ambos têm o mesmo valor de p! A chamada Alguma idéia sobre isso?
Atualizar Decidi usar ctypes. Muito facil