PyBind11:绑定使用双指针的函数

Qua*_*sar 3 c++ c++11 pybind11

我想用 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);     
}
Run Code Online (Sandbox Code Playgroud)

Jas*_*der 7

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

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

因此,您只想将它​​与一种本身可以将整个事物公开为 a 的类型结合起来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());
});
Run Code Online (Sandbox Code Playgroud)

(如果您parse_args实际上需要一个const char **,则可以删除const_cast)。