【问题标题】:Debugging python SWIG object调试 python SWIG 对象
【发布时间】:2021-12-30 16:56:47
【问题描述】:

我正在编写一些新的 python 代码来替换为遗留系统编写的一些代码。遗留系统通过 SWIG 包装器引用一些 C++ 代码。遗留 Python 代码中有一个特殊点,它使用 SWIG 包装器中的一种方法,其输出我不明白如何解释。

*' at 0xed1e0a88> >

的代理

这是从 python 角度看代码的相关部分:

#import swig wrapper hgrm_messages
import hgrm_messages

#declare an object with the JobInstanceDefinition class through SWIG  
definition = hgrm_messages.JobInstanceDefinition()

#loop through arguments list and place into a vector using the push_back method through SWIG
for argument in agruments:
    definition.arguments.push_back(str(argument))

当我调试这段代码时,define.arguments 的值显示为(与上面相同):

*' at 0xed1e0a88> >

的代理

我正在寻求一些帮助来理解这个输出的价值。我已经熟悉 SWIG 并且对 C++ 有一些工作知识(我的 Python 知识要丰富得多)。我不确定如何将此输出追溯到产生它的 C++ 函数。

任何帮助或想法表示赞赏!

【问题讨论】:

    标签: python c++ swig


    【解决方案1】:

    下面的显示是 SWIG 为其包装的矢量模板的代理包装器对象的默认表示:

    <hub_logging.StringList; proxy of <Swig Object of type 'std::vector< std::string > *' at 0xed1e0a88> >
    

    这是一个 .i 文件和用例的最小示例:

    %module test
    
    %include <std_vector.i>  // SWIG typemaps for std::vector<>
    %include <std_string.i>  // SWIG typemaps for std::string
    
    // Gives an alias and instructs SWIG to generate wrappers
    // for this specific template instantiation.
    %template(StringList) std::vector<std::string>;
    
    // Generate both code and a wrapper for the following class.
    %inline %{
    class Definition {
    public:
        std::vector<std::string> arguments;
    };
    %}
    

    演示:

    >>> import test
    >>> definition = test.Definition()
    >>> definition.arguments
    <test.StringList; proxy of <Swig Object of type 'std::vector< std::string > *' at 0x00000289E88CA120> >
    >>> definition.arguments.push_back("arg1")
    >>> definition.arguments.push_back("arg2")
    >>> list(definition.arguments)  # wrapper is iterable, convert to Python list
    ['arg1', 'arg2']
    

    如果您不喜欢默认显示表示,您可以在 SWIG 中覆盖它,类似于为 Python 覆盖 __repr__(),方法是向矢量模板添加扩展:

    %extend std::vector<std::string> {
        std::string __repr__() {
            std::string tmp {"StringList(["};
            for(size_t i = 0; i < $self->size() - 1; ++i)
                tmp += "\"" + $self->at(i) + "\", ";
            if($self->size() > 0)
                tmp += "\"" + $self->at(self->size() - 1) + "\"";
            tmp += "])";
            return tmp;
        }
    };
    

    现在演示输出是:

    >>> import test
    >>> definition = test.Definition()
    >>> definition.arguments.push_back('arg1')
    >>> definition.arguments
    StringList(["arg1"])
    >>> definition.arguments.push_back('arg2')
    >>> definition.arguments
    StringList(["arg1", "arg2"])
    

    请注意,我的扩展程序没有正确转义字符串中嵌入的引号,但您应该明白了。

    【讨论】:

    • 回到这个话题。谢谢!我需要的一点信息是包装器创建了一个 python 可迭代对象,需要将其传递给 list 之类的 python 函数以使其可读。现在我需要更好地理解编码。我注意到参数字符串中存在前缀 u(表示 unicode)。但是当通过 SWIG 包装器传递给 .push_back 方法并被视为列表时。前面的 u 不见了。
    • @ChaseSchuette 这不是一个真正的可迭代对象。它实际上是一个数组,但默认显示表示不显示元素。 list() 提取元素,但您也可以使用 for item in definition.arguments: print(item),或者只是 print(definition.arguments[0])。或者正如我提供的那样,您可以覆盖显示表示。 std::string 的 SWIG 类型映射接受 Unicode 字符串,但在传递给 C++ 时将其编码为 UTF-8。在 Python 3 中,u"string""string" 都是 Unicode 字符串,前面的 u 是为了向后兼容 Python 2 移植的代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-24
    • 2023-04-08
    • 1970-01-01
    相关资源
    最近更新 更多