【问题标题】:SWIG: Access Array of Structs in PythonSWIG:在 Python 中访问结构数组
【发布时间】:2021-11-30 01:25:18
【问题描述】:

假设我有以下static constexpr c 结构数组:

#include <cstdint>

namespace ns1::ns2 {
    struct Person {
        char name[32];
        uint8_t age;    
    };
    static constexpr Person PERSONS[] = {
        {"Ken", 8},
        {"Cat", 27}
    };
}

如何使用 swig 在 python 中访问ns1::ns2::PERSONS 中的元素?

我能想到的一种方法是在 swig 接口文件中创建一个类似 const Person&amp; get(uint32_t index) 的访问器。 Tho,我想知道是否有一种更优雅的方式,我不必为每个 c 结构数组创建访问器函数。

谢谢!

【问题讨论】:

    标签: c++ python-3.x linux swig


    【解决方案1】:

    我能想到的一种方法是在 swig 接口文件中创建一个类似 const Person& get(uint32_t index) 的访问器。

    根据SWIG documentation中的5.4.5 Arrays,是这样的:

    %module test
    
    %include <stdint.i>
    
    %inline %{
    #include <cstdint>
    
    namespace ns1::ns2 {
        struct Person {
            char name[32];
            uint8_t age;
        };
        static constexpr Person PERSONS[] = {
            {"Ken", 8},
            {"Cat", 27}
        };
    }
    
    // helper function
    const ns1::ns2::Person* Person_get(size_t index) {
        if(index < sizeof(ns1::ns2::PERSONS) / sizeof(ns1::ns2::Person))  // protection
            return ns1::ns2::PERSONS + index;
        else
            return nullptr;
    }
    %}
    

    演示:

    >>> import test
    >>> test.PERSONS.name # can only access the first element
    'Ken'
    >>> test.Person_get(1).name
    'Cat'
    >>> test.Person_get(2).name
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'NoneType' object has no attribute 'name'
    

    SWIG 还可以使用 11.2.2 carrays.i 为您生成数组包装器,但没有边界检查:

    %module test
    
    %include <stdint.i>
    
    %inline %{
    #include <cstdint>
    
    namespace ns1::ns2 {
        struct Person {
            char name[32];
            uint8_t age;
        };
        static constexpr Person PERSONS[] = {
            {"Ken", 8},
            {"Cat", 27}
        };
    }
    %}
    
    %include <carrays.i>
    %array_functions(ns1::ns2::Person,arrayPerson);
    

    演示:

    >>> import test
    >>> test.arrayPerson_getitem(test.PERSONS,1).name
    'Cat'
    

    【讨论】:

    • 谢谢。我希望有一天,swig 可以提供更“自然”的东西,用户可以访问像 test.PERSONS[0] 这样的元素...
    • 其实还有一个问题和上面同一个代码sn-p有关。如果我将 const cv-qualifier 添加到成员变量名称和年龄,似乎 SWIG 生成了一些无效代码(在这种情况下 cv-qualifier 是有效的),我收到了这个错误,error: use of deleted function ‘ns1::ns2::Person::Person()’3096 | return (new ns1::ns2::Person[nelements]());似乎 SWIG 在返回时总是尝试分配一个新对象,即使我请求返回一个引用。
    • @HCSF 如果您想要更自然,请尝试使用std::vector 而不是数组。
    猜你喜欢
    • 1970-01-01
    • 2011-12-28
    • 1970-01-01
    • 2011-09-04
    • 1970-01-01
    • 1970-01-01
    • 2014-01-21
    • 2018-06-08
    • 2017-01-28
    相关资源
    最近更新 更多