【问题标题】:Python SWIG: convert C++ return parameter to return value, and convert raw C++ type to Python typePython SWIG:将 C++ 返回参数转换为返回值,并将原始 C++ 类型转换为 Python 类型
【发布时间】:2018-03-05 23:49:10
【问题描述】:

我正在尝试为 C++ 库修改现有的 SWIG Python 接口,为更多功能添加 Python 包装器,非常感谢有 SWIG 经验的人提供的帮助。

具体来说,我正在开发一个具有这样签名的函数:

void execute(int x, double y, ResultType& result1, ResultType& result2);

此函数接受两个空的 ResultType 对象并将它们填充为输出参数。在 Python 中,这必须转换为只接受 xy 的函数,然后返回 result1result2 的元组。

ResultType 是一种在整个库中广泛使用的容器类型。

typemap(in)

从研究中,我想我明白我需要为 result1 和 result2 添加一个类型映射“in”,它会吞下参数并将它们保存到临时变量中。我还发现引用被 SWIG 转换为指针,因此 &temp 而不是 temp。这是我的“输入”类型图:

typemap(in, numinputs=0) ResultType& result1 (ResultType temp) {
    $1 = &temp;
}

typemap(in, numinputs=0) ResultType& result2 (ResultType temp) {
    $1 = &temp;
}

类型映射(参数)

接下来,我添加了一个类型映射“argout”,将值附加到返回元组:

%typemap(argout) ResultType& result1 {
    $result = SWIG_Python_AppendOutput($result, temp$argnum);
}

%typemap(argout) ResultType& result2 {
    $result = SWIG_Python_AppendOutput($result, temp$argnum);
}

但是,这显然行不通,因为temp$argnum 将是原始C++ 类型ResultType,而我需要PyObject * 才能附加到元组。 ResultType 已经有一个有效的 SWIG 包装器。因此,在 Python 中,我可以毫无问题地调用 ResultType() 来构造它的实例。假设到目前为止我走在正确的轨道上,如何将原始 C++ ResultType 对象转换为属于 SWIG 生成的 ResultType 包装器的 PyObject *? (对不起,如果太多细节,我试图避免“XY问题”)

【问题讨论】:

    标签: python c++ swig


    【解决方案1】:

    就像 $1 是对输入类型映射中的 Python 输入对象的引用一样,$1 是对 argout 类型映射中的 C++ 输出变量的引用。使用它,您可以为该数据生成一个 Python 对象并将其附加到结果中。

    这是一个适用于 Windows 的功能示例:

    test.h

    #ifdef EXPORT
    #define API __declspec(dllexport)
    #else
    #define API __declspec(dllimport)
    #endif
    
    struct ResultType
    {
        int x;
        double y;
    };
    
    API void execute(int x, double y, ResultType& result1, ResultType& result2);
    

    test.cpp

    #define EXPORT
    #include "test.h"
    
    API void execute(int x, double y, ResultType& result1, ResultType& result2)
    {
        result1.x = 2 * x;
        result1.y = 2 * y;
        result2.x = 3 * x;
        result2.y = 3 * y;
    }
    

    test.i

    %module test
    
    %{
    #include "test.h"
    %}
    
    %include <windows.i>
    
    %typemap(in,numinputs=0) ResultType& %{
        // Create a persistent object to hold the result;
        $1 = new ResultType;
    %}
    
    %typemap(argout) ResultType& (PyObject* tmp) %{
        // Store the persistent object in a PyObject* that will be destroyed
        // when it goes out of scope.
        tmp = SWIG_NewPointerObj($1, $1_descriptor, SWIG_POINTER_OWN);
        $result = SWIG_Python_AppendOutput($result, tmp);
    %}
    
    %include "test.h"
    

    输出

    >>> import test
    >>> r = test.execute(2,3)
    >>> r[0].x
    4
    >>> r[0].y
    6.0
    >>> r[1].x
    6
    >>> r[1].y
    9.0
    

    【讨论】:

    • 你的小例子效果很好!谢谢!这是我错过的魔法咒语……SWIG_NewPointerObj($1, $1_descriptor, SWIG_POINTER_OWN);
    猜你喜欢
    • 2020-11-24
    • 1970-01-01
    • 1970-01-01
    • 2021-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-30
    • 1970-01-01
    相关资源
    最近更新 更多