Swig包装typedef结构

时间:2014-10-25 21:32:13

标签: swig

尝试包装二进制库,其中头文件定义typedef struct x x_t,其中尚未定义struct x。如何定义一个接口文件,允许python在下面定义的函数中使用类型defed结构。

myconnection.h

typedef int myConnectionError;

// Note: this struct does not exist
// The typedef is done to strengthen type checking
typedef struct _myConnectionHandle* myConnectionHandle;

myConnectionError myConnectionOpen( const char *x , const char *y , myConnectionHandle *hand);

myconnection.i

% module myconnection
%{
#include "myconnection.h"
%}

%include "myconnection.h"

工作C / C ++代码的示例

myConnectionHandle chandle;
myConnectionError error;
error = myConnectionOpen("foo","bar",&chandle);

预期的Python代码

import myconnection
handle = myconnection.myConnectionHandle
err = myconnection.myConnectionOpen("foo","1080",handle)

Python结果

Python 2.6.6 (r266:84292, Jan 22 2014, 09:42:36) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import myconnection
>>> handle = myconnection.myConnectionHandle()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'myConnectionnHandle'

1 个答案:

答案 0 :(得分:1)

由于Python不支持输出参数,因此典型的方法是创建一组压缩必须传递输出参数的类型映射,而是在内部使用附加到返回值的临时值。这是一个将句柄转换为Python整数对象的最小例子:

%typemap(in) myConnectionHandle %{
    $1 = (myConnectionHandle)PyLong_AsVoidPtr($input);
%}

%typemap(in,numinputs=0) myConnectionHandle* (void* tmp) %{
    $1 = (myConnectionHandle*)&tmp;
%}
%typemap(argout) myConnectionHandle* %{
    $result = SWIG_Python_AppendOutput($result,PyLong_FromVoidPtr(*$1));
%}

第一个typemap将Python整数转换为myConnectionHandle,以用作函数的输入。

第二个typemap告诉SWIG在输入时忽略myConnectionHandle*,因为它是一个输出参数,在调用函数时只需使用临时值来存储句柄。

第三个typemap告诉SWIG将返回的句柄值附加到返回结果,必要时将其转换为[retval, handle]列表。

以下是使用myconnection.h的示例,但我添加了一个函数来将句柄作为输入,并添加了函数的一些虚拟实现以使其进行编译。

%module myconnection
%{
    #include "myconnection.h"
    myConnectionError myConnectionOpen( const char *x , const char *y , myConnectionHandle *hand)
    {
        static int something;
        *hand = (myConnectionHandle)&something;
        return 0;
    }
    void useConnection(myConnectionHandle h)
    {
    }
%}

%typemap(in) myConnectionHandle %{
    $1 = (myConnectionHandle)PyLong_AsVoidPtr($input);
%}

%typemap(in,numinputs=0) myConnectionHandle* (void* tmp) %{
    $1 = (myConnectionHandle*)&tmp;
%}

%typemap(argout) myConnectionHandle* %{
    $result = SWIG_Python_AppendOutput($result,PyLong_FromVoidPtr(*$1));
%}

%include "myconnection.h"

输出:

>>> import myconnection
>>> retval, handle = myconnection.myConnectionOpen('foo','bar')
>>> myconnection.useConnection(handle)
>>>