通过SWIG C到Python的:不能得到无效**参数持有的价值 [英] C to Python via SWIG: can't get void** parameters to hold their value
问题描述
我有一个C接口,看起来像这样(简体):
I have a C interface that looks like this (simplified):
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);
}
您会注意到操作()分配缓冲区P,即GetFieldValue查询P,以及清理释放页。我没有在C接口的任何控制 - 即code广泛用于其他地方。
You'll note that Operation() allocates the buffer p, that GetFieldValue queries p, and that Cleanup frees p. I don't have any control over the C interface -- that code is widely used elsewhere.
我想从Python中通过痛饮称之为code,但我无法找到如何将指针传递给一个指针任何很好的例子 - 和检索其值
I'd like to call this code from Python via SWIG, but I was unable to find any good examples of how to pass a pointer to a pointer -- and retrieve its value.
我觉得这样做的正确方法是使用typemaps的,所以我定义一个接口,将自动取消引用p表示我对C端:
I think the correct way to do this is by use of typemaps, so I defined an interface that would automatically dereference p for me on the C side:
%typemap(in) void** {
$1 = (void**)&($input);
}
不过,我无法得到以下蟒蛇code的工作:
However, I was unable to get the following python code to work:
import test
p = None
theAnswer = 0.0f
if test.Operation(p):
theAnswer = test.GetFieldValue(p)
test.Cleanup(p)
调用后test.Operation()中,p总是保持无它的初始值。
After calling test.Operation(), p always kept its initial value of None.
搞清楚正确的方式来做到这一点痛饮会大大AP preciated任何帮助。否则,我可能只写围绕C code,它不必处理指针停Python中的C ++包装。然后包裹的是的包装与痛饮。有人阻止我!
Any help with figuring out the correct way to do this in SWIG would be much appreciated. Otherwise, I'm likely to just write a C++ wrapper around the C code that stops Python from having to deal with the pointer. And then wrap that wrapper with SWIG. Somebody stop me!
编辑:
感谢 Jorenko ,我现在有以下SWIG接口:
Thanks to Jorenko, I now have the following SWIG interface:
% 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);
}
}
使用此痛饮接口,Python code是如下:
The python code that uses this SWIG interface is as follows:
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 code,test.GetFieldValue(p)返回胡言乱语,但test.gfv(p)返回正确的值。我已经插入调试code到类型映射为无效*,且都有p的相同的价值!该呼叫有关的任何想法?
Oddly, in the python code, test.GetFieldValue(p) returns gibberish, but test.gfv(p) returns the correct value. I've inserting debugging code into the typemap for void*, and both have the same value of p! The call Any ideas about that?
更新:我已经决定使用ctypes的。容易多了。
Update: I've decided to use ctypes. MUCH easier.
推荐答案
我theller同意,你应该使用ctypes的来代替。它总是比思考更容易typemaps
I agree with theller, you should use ctypes instead. It's always easier than thinking about typemaps.
但是,如果你在使用痛饮是死心塌地,你需要做的是做一个类型映射为无效**
,返回新分配的无效*
:
But, if you're dead set on using swig, what you need to do is make a typemap for void**
that RETURNS the newly allocated void*
:
%typemap (in,numinputs=0) void** (void *temp)
{
$1 = &temp;
}
%typemap (argout) void**
{
PyObject *obj = PyCObject_FromVoidPtr(*$1);
$result = PyTuple_Pack(2, $result, obj);
}
然后在你的Python是这样的:
Then your python looks like:
import test
success, p = test.Operation()
theAnswer = 0.0f
if success:
theAnswer = test.GetFieldValue(p)
test.Cleanup(p)
编辑:
我预计痛饮处理一个简单的按值无效*
ARG优雅地对自己,但为了以防万一,这里的痛饮code包住无效*
为GetFieldValue()和清理():
I'd expect swig to handle a simple by-value void*
arg gracefully on its own, but just in case, here's swig code to wrap the void*
for GetFieldValue() and Cleanup():
%typemap (in) void*
{
$1 = PyCObject_AsVoidPtr($input);
}
这篇关于通过SWIG C到Python的:不能得到无效**参数持有的价值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!