我有一个看起来像这样(简化)的 C 接口:
extern bool Operation(void ** ppData);
extern float GetFieldValue(void* pData);
extern void Cleanup(p);
使用如下:
void * p = NULL;
float theAnswer = 0.0f;
if (Operation(&p))
{
theAnswer = GetFieldValue(p);
Cleanup(p);
}
您会注意到 Operation() 分配缓冲区 p,GetFieldValue 查询 p,而 Cleanup 释放 p。我对 C 接口没有任何控制权——该代码在其他地方被广泛使用。
我想通过SWIG从 Python 调用此代码,但我找不到任何关于如何将指针传递给指针并检索其值的好的示例。
我认为正确的方法是使用类型映射,所以我定义了一个接口,它会在 C 端为我自动取消引用 p:
%typemap(in) void** {
$1 = (void**)&($input);
}
但是,我无法让以下 python 代码工作:
import test
p = None
theAnswer = 0.0f
if test.Operation(p):
theAnswer = test.GetFieldValue(p)
test.Cleanup(p)
调用 test.Operation() 后,p 始终保持其初始值 None。
任何帮助找出在 SWIG 中执行此操作的正确方法将不胜感激。否则,我可能只是围绕 C 代码编写一个 C++ 包装器,以阻止 Python 处理指针。然后用 SWIG包装该包装器。有人阻止我!
编辑:
感谢Jorenko,我现在有了以下 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);
}
}
使用这个 SWIG 接口的 python 代码如下:
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)
奇怪的是,在 python 代码中, test.GetFieldValue(p) 返回乱码,但 test.gfv(p) 返回正确的值。我已经将调试代码插入到 void* 的类型映射中,并且两者都具有相同的 p 值!电话 对此有何想法?
更新:我决定使用 ctypes。容易得多。