首页 > 解决方案 > 使用 pybind11 创建一个 numpy python 字符串数组

问题描述

我正在尝试使用 pybind11 从 c++ 修改一个 numpy 字符串数组。我正在使用的代码具有以下结构:

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;
}

我面临的问题是此错误消息:

pybind11/numpy.h:1114:19:错误:静态断言失败:尝试使用非 POD 或未实现的 POD 类型作为 numpy dtype static_assert(is_pod_struct::value, "尝试使用非 POD 或未实现的 POD 类型作为一个 numpy dtype");

不知道有什么问题。在 python 中,您可以创建 numpy 字符串数组,那么我做错了什么?谢谢。

标签: pybind11

解决方案


pybind11(在 v2.2.3、CentOS7、python3.6.5 上测试)通过使用pybind11::array_t< std::array<char, N> >orchar[N]类型支持固定长度的字符串。为了以防万一,您可能需要用空值填充字符串,因为 C 样式字符串的标准缺陷适用(例如 N-1 个可用字符)。我更喜欢与它一起工作,std::array因为它不会衰减到char*不调用.data()使您的意图对其他读者更清楚的情况下。

所以对于 16 字节字符串的向量,一些伪代码看起来像这样:

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

然后在python中:

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

推荐阅读