Say I have the following static constexpr
array of c struct:
#include <cstdint> namespace ns1::ns2 { struct Person { char name[32]; uint8_t age; }; static constexpr Person PERSONS[] = { {"Ken", 8}, {"Cat", 27} }; }
How can I access elements in ns1::ns2::PERSONS
in python by using swig?
One way I can think of is to create a accessor like const Person& get(uint32_t index)
in the swig interface file. Tho, I wonder whether there is a more elegant way that I don’t have to create an accessor function for each array of c struct.
Thanks!
Advertisement
Answer
One way I can think of is to create a accessor like const Person& get(uint32_t index) in the swig interface file.
According to 5.4.5 Arrays in the SWIG documentation, that’s the way to do it:
%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; } %}
Demo:
>>> 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 can also generate array wrappers for you with 11.2.2 carrays.i, but there is no bounds checking:
%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);
Demo:
>>> import test >>> test.arrayPerson_getitem(test.PERSONS,1).name 'Cat'