【问题标题】:SWIG struct pointer as output parameterSWIG 结构指针作为输出参数
【发布时间】:2019-04-22 13:47:32
【问题描述】:

我有一个结构:

struct some_struct_s {
   int arg1;
   int arg2;
};

我有一个 C 函数:

int func(some_struct_s *output);

在我的 SWIG 文件中,两者都是 %included

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

int_val, some_struct_output = func()

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

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

【问题讨论】:

    标签: python c swig


    【解决方案1】:

    来自documentation

    11.5.7 "argout" 类型映射

    “argout”类型映射用于从参数返回值。这最常用于为需要返回多个值的 C/C++ 函数编写包装器。 “argout”类型映射几乎总是与“in”类型映射结合——可能会忽略输入值....

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

    %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;
    }
    
    %}
    

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

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

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

    %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
    %}
    

    演示:

    >>> 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
    

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

    %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;
    }
    
    %}
    

    演示:

    >>> 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
    

    【讨论】:

    • 谢谢。没有这个,我注意到我可以在一行代码上实例化一个空的some_struct_s 并传入。当函数返回时,内容是不透明的。这样做的好处是我不必编写特定于语言的类型图。我希望有一种方法可以表示参数应该在末尾,而不必为 argout 类型映射中的每个元素编写输出语言特定的 api 代码。我应该放弃希望吗?
    • @MichaelLabbé 没有找到不编写类型映射的方法,但您可以通过使用一些 SWIG 宏来避免语言细节。我会更新一个例子。
    猜你喜欢
    • 1970-01-01
    • 2011-04-15
    • 1970-01-01
    • 2011-10-24
    • 1970-01-01
    • 2013-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多