【问题标题】:PyBind11: binding a function that uses double pointersPyBind11:绑定使用双指针的函数
【发布时间】:2018-08-18 02:57:20
【问题描述】:

我想用 PyBind11 绑定一个 C++ 函数。问题是这个函数有一个带双指针的参数,编译器会报错

error: cannot initialize a parameter of type 'char **' with an rvalue of type 'typename make_caster<char **>::cast_op_type<typename std::add_rvalue_reference<char**>::type>' (aka 'char *').

具体代码如下:

#include <pybind11/pybind11.h>

#include <iostream>

namespace py = pybind11;

void parse_args(int argn__, char** argv__)
{
  for(int i = 1; i < argn__; ++i)
    {
      std::cout<< argv__[i];
    }
}

PYBIND11_MODULE(argv_bind, m) {
   m.def("parse_args", &parse_args);     
}

【问题讨论】:

  • 可能pybind11无法判断什么python类相当于双指针。 python 代码如何提供指向 c++ 扩展的双指针? python 端可以改为给出一个 numpy 数组或 python 列表,它们在 c++ 端被转换为py::array、Eigen 数组或std::list。顺便说一句,python 的sys.argvargparse 已经可以解析命令行参数了。您可以使用这些并将结果通过boolstd::stringint 等传递给 c++ 扩展。由于解析命令行参数不是性能关键,python 可以做到这一点。

标签: c++ c++11 pybind11


【解决方案1】:

对于非简单参数类型(例如您的char **),您必须包装函数本身,其中您的包装器提供了从简单类型或 Python 对象到所需类型的逻辑。

在这种情况下,char * 实际上是一个非常不安全的类型,因为它没有进行内存清理;为了使这项工作稳健地进行,您需要获取std::strings,然后您可以从中通过c_str() 方法访问char *。 (在 pybind11 中,即使您使用 char * 参数,它们实际上也只是指向 std::string 参数的指针:Python API 故意让调用者访问 Python 字符串的内部存储)。

那么你只想将它与一个可以将整个事情暴露为char ** 的类型结合起来,这几乎就是std::vector 的设计目的。这是一个适合您的示例代码的包装器:

#include <pybind11/stl.h>

m.def("parse_args", [](std::vector<std::string> args) {
    std::vector<char *> cstrs;
    cstrs.reserve(args.size());
    for (auto &s : args) cstrs.push_back(const_cast<char *>(s.c_str()));
    return parse_args(cstrs.size(), cstrs.data());
});

(如果您的parse_args 实际使用const char **,您可以放弃const_cast)。

【讨论】:

  • 如果您也可以看看我的问题here,我将不胜感激。提前致谢。
猜你喜欢
  • 2022-07-06
  • 1970-01-01
  • 1970-01-01
  • 2013-10-31
  • 1970-01-01
  • 1970-01-01
  • 2017-08-22
  • 2021-09-23
  • 2012-03-09
相关资源
最近更新 更多