gioni_go
gioni_go

Reputation: 99

Creating a numpy python string array with pybind11

I am trying to modify a numpy string array from c++ with pybind11. The code i am using has the following structure:

py::array_t<py::str> process_array(py::array_t<py::str> input);

PYBIND11_EMBEDDED_MODULE(fast_calc, m) {
  m.def("process_array", process_array);
}

py::array_t<py::str> process_array(py::array_t<py::str> input) {
  auto buf = input.request();
  cout << &buf;

  return input;
}

The problem i face is this error message:

pybind11/numpy.h:1114:19: error: static assertion failed: Attempt to use a non-POD or unimplemented POD type as a numpy dtype static_assert(is_pod_struct::value, "Attempt to use a non-POD or unimplemented POD type as a numpy dtype");

Not sure whats the catch. In python you can create numpy string arrays so what am i doing wrong? Thanks.

Upvotes: 1

Views: 3071

Answers (1)

dworvos
dworvos

Reputation: 176

Fixed length strings are supported in pybind11 (tested on v2.2.3, CentOS7, python3.6.5) by using the pybind11::array_t< std::array<char, N> > or char[N] type. Likely you'll want to pad out the string with null values just in case, as the standard pitfalls of C-style strings apply (e.g. N-1 useable characters). I prefer working with std::array as it doesn't decay to a char* without calling .data() making your intentions clearer to other readers.

So some psuedocode would look like this for a vector of 16 byte strings:

using np_str_t = std::array<char, 16>;
pybind11::array_t<np_str_t> cstring_array(vector.size());
np_str_t* array_of_cstr_ptr = reinterpret_cast<np_str_t*>(cstring_array.request().ptr);

for(const auto & s : vector)
{
   std::strncpy(array_of_cstr_ptr->data(), s.data(), array_of_cstr_ptr->size());
   array_of_cstr_ptr++;
}

return cstring_array; //numpy array back to python code

And then in python:

array([b'ABC', b'XYZ'], dtype='|S16')

Upvotes: 3

Related Questions