SWIG 结构指针作为输出参数 [英] SWIG struct pointer as output parameter

查看:37
本文介绍了SWIG 结构指针作为输出参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个结构:

struct some_struct_s {int arg1;int arg2;};

我有一个 C 函数:

int func(some_struct_s *output);

两者都 %included 到我的 SWIG 文件中.

我希望将 some_struct_s *output 视为输出参数.Python 示例:

int_val, some_struct_output = func()

输出参数"包含在 POD 类型的手册中(第 10.1.3 节),但不适用于非 POD 类型.

如何告诉 SWIG 我希望 some_struct_s *output 成为输出参数?

解决方案

来自 文档:

<块引用>

11.5.7 争论"类型图

争论"typemap 用于从参数返回值.这最常用于为需要返回多个值的 C/C++ 函数编写包装器.争论"typemap 几乎总是与in"组合在一起.typemap---可能忽略输入值....

这是您的代码的完整示例(为简洁起见,没有错误检查):

%module 测试//声明一个输入类型映射,抑制需要任何输入和//声明一个临时堆栈变量来保存返回数据.%typemap(in,numinputs=0) some_struct_s* (some_struct_s tmp) %{$1 = &tmp;%}//声明一个输出参数类型映射.在这种情况下,我们将使用//一个保存结构数据的元组(没有错误检查).%typemap(argout) some_struct_s* (PyObject* o) %{o = PyTuple_New(2);PyTuple_SET_ITEM(o,0,PyLong_FromLong($1->arg1));PyTuple_SET_ITEM(o,1,PyLong_FromLong($1->arg2));$result = SWIG_Python_AppendOutput($result,o);%}//而不是头文件,我们将在内联声明此代码.//这包括包装器中的代码,以及告诉 SWIG//以目标语言创建包装器.%排队 %{struct some_struct_s {int arg1;int arg2;};int func(some_struct_s *输出){输出-> arg1 = 1;输出-> arg2 = 2;返回0;}%}

下面的演示.请注意,int 返回值为零以及作为元组的输出参数作为列表返回.

<预><代码>>>>进口测试>>>测试.func()[0, (1, 2)]

如果你不想要类型映射,你也可以注入代码来创建对象并返回它以对用户隐藏它:

%module 测试%rename(_func) 函数;//给包装器一个不同的名字%排队 %{struct some_struct_s {int arg1;int arg2;};int func(struct some_struct_s *output){输出-> arg1 = 1;输出-> arg2 = 2;返回0;}%}//声明你的接口%pythoncode%{定义函数():s = some_struct_s()r = _func(s)返回 r,s%}

演示:

<预><代码>>>>进口测试>>>r,s=test.func()>>>r0>>>秒<test.some_struct_s;<0x000001511D70A880处类型为'some_struct_s *'的Swig对象的代理>>>>s.arg11>>>arg22

如果您仔细选择 SWIG 宏,您可以使类型映射语言不可知:

%module 测试%typemap(in,numinputs=0) struct some_struct_s *output %{$1 = malloc(sizeof(struct some_struct_s));%}%typemap(argout) struct some_struct_s* 输出 {%append_output(SWIG_NewPointerObj($1,$1_descriptor,1));}%排队 %{struct some_struct_s {int arg1;int arg2;};int func(struct some_struct_s *output){输出-> arg1 = 1;输出-> arg2 = 2;返回0;}%}

演示:

<预><代码>>>>进口测试>>>r,s=test.func()>>>r0>>>秒<test.some_struct_s;<0x000001DD0425A700 处类型为some_struct_s *"的 Swig 对象的代理>>>>s.arg11>>>arg22

I have a struct:

struct some_struct_s {
   int arg1;
   int arg2;
};

I have a C function:

int func(some_struct_s *output);

Both are %included into my SWIG file.

I want some_struct_s *output to be treated like an output parameter. Python example:

int_val, some_struct_output = func()

"Output parameters" is covered in the manual for POD-types (sec 10.1.3), but not for non-POD types.

How do I tell SWIG I want some_struct_s *output to be an output parameter?

解决方案

From the documentation:

11.5.7 "argout" typemap

The "argout" typemap is used to return values from arguments. This is most commonly used to write wrappers for C/C++ functions that need to return multiple values. The "argout" typemap is almost always combined with an "in" typemap---possibly to ignore the input value....

Here's a complete example for your code (no error checking for brevity):

%module test

// Declare an input typemap that suppresses requiring any input and
// declare a temporary stack variable to hold the return data.
%typemap(in,numinputs=0) some_struct_s* (some_struct_s tmp) %{
    $1 = &tmp;
%}

// Declare an output argument typemap.  In this case, we'll use
// a tuple to hold the structure data (no error checking).
%typemap(argout) some_struct_s* (PyObject* o) %{
    o = PyTuple_New(2);
    PyTuple_SET_ITEM(o,0,PyLong_FromLong($1->arg1));
    PyTuple_SET_ITEM(o,1,PyLong_FromLong($1->arg2));
    $result = SWIG_Python_AppendOutput($result,o);
%}

// Instead of a header file, we'll just declare this code inline.
// This includes the code in the wrapper, as well as telling SWIG
// to create wrappers in the target language.
%inline %{

struct some_struct_s {
   int arg1;
   int arg2;
};

int func(some_struct_s *output)
{
    output->arg1 = 1;
    output->arg2 = 2;
    return 0;
}

%}

Demo below. Note that the int return value of zero as well as the output parameter as a tuple are returned as a list.

>>> import test
>>> test.func()
[0, (1, 2)]

If you don't want typemaps, you can also inject code to create the object and return it to hide it from the user:

%module test

%rename(_func) func; // Give the wrapper a different name

%inline %{

struct some_struct_s {
   int arg1;
   int arg2;
};

int func(struct some_struct_s *output)
{
    output->arg1 = 1;
    output->arg2 = 2;
    return 0;
}

%}

// Declare your interface
%pythoncode %{
def func():
    s = some_struct_s()
    r = _func(s)
    return r,s
%}

Demo:

>>> import test
>>> r,s=test.func()
>>> r
0
>>> s
<test.some_struct_s; proxy of <Swig Object of type 'some_struct_s *' at 0x000001511D70A880> >
>>> s.arg1
1
>>> s.arg2
2

You can make the typemap language agnostic if you carefully select SWIG macros:

%module test

%typemap(in,numinputs=0) struct some_struct_s *output %{
    $1 = malloc(sizeof(struct some_struct_s));
%}

%typemap(argout) struct some_struct_s* output {
    %append_output(SWIG_NewPointerObj($1,$1_descriptor,1));
}

%inline %{

struct some_struct_s {
   int arg1;
   int arg2;
};

int func(struct some_struct_s *output)
{
    output->arg1 = 1;
    output->arg2 = 2;
    return 0;
}

%}

Demo:

>>> import test
>>> r,s=test.func()
>>> r
0
>>> s
<test.some_struct_s; proxy of <Swig Object of type 'some_struct_s *' at 0x000001DD0425A700> >
>>> s.arg1
1
>>> s.arg2
2

这篇关于SWIG 结构指针作为输出参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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