I have a struct
that contains a C-style array data member. I'd like to have this struct exposed to Python, and this data member be accessible as a list in Python.
struct S
{
char arr[4128];
};
void foo( S const * )
{}
BOOST_PYTHON_MODULE( test )
{
using namespace boost::python;
class_<S>( "S" )
.def_readwrite( "arr", &S::arr )
;
def( "foo", foo );
}
The code above fails to build
error C2440: '=' : cannot convert from 'const char [4128]' to 'char [4128]'
C-style arrays are not assignable, so the error makes sense. The code compiles if I change the data member to a plain char
instead of an array.
I cannot replace the array with an std::array
or some other container because the structure is being consumed by a C API. The only solution I can think of is to write a couple of wrappers and do the following
struct S1
that duplicates S
except it'll have an std::array
instead of a C-style arrayfoo_wrapper
that accepts a S1 const *
, copies the contents over to an S
instance and calls foo
to_python_converter
to convert the std::array
to a Python listThis should work, and I'm not too concerned about the data copying at this point, but it'd be nice if I could avoid it and expose the array directly without having to jump through all these hoops.
So the question is, how can I expose that C-style array data member to Python as a list?
As you've seen, Boost.Python unfortunately doesn't provide automatic converters for C arrays, and even the STL container wrappers it provides aren't how I'd recommend approaching this (at least if your real problem is similar to your example one in terms of how large the array is, and if you know you want to expose it as a true Python tuple).
I'd recommend writing a function that converts the C array into a Python tuple, using either the Python C-API directly, or its boost::python wrappers, and then exposing the data member via a property. While you could avoid data copying by using a NumPy array instead of a tuple, for small arrays that's not worth the effort.
For example:
namespace bp = boost::python;
bp::tuple wrap_arr(S const * s) {
bp::list a;
for (int i = 0; i < 10; ++i) {
a.append(s->arr[i]);
}
return bp::tuple(a);
}
BOOST_PYTHON_MODULE( test ) {
bp::class_<S>( "S" )
.add_property("arr", wrap_arr)
;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With