通过SWIG C到Python的:不能得到无效**参数持有的价值 [英] C to Python via SWIG: can't get void** parameters to hold their value

查看:173
本文介绍了通过SWIG C到Python的:不能得到无效**参数持有的价值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆