PyBind11:绑定一个使用双指针的函数
PyBind11: binding a function that uses double pointers
我想用 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);
}
对于 non-simple 参数类型(例如像你的 char **
)你必须包装函数本身,你的包装器提供了从更简单的类型或 Python 对象到所需的类型。
在这种情况下,char *
实际上是一种非常不安全的类型,因为它不会进行内存清理;为了使这项工作稳健地进行,您需要使用 std::string
s,然后您可以从中通过 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
)。
我想用 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);
}
对于 non-simple 参数类型(例如像你的 char **
)你必须包装函数本身,你的包装器提供了从更简单的类型或 Python 对象到所需的类型。
在这种情况下,char *
实际上是一种非常不安全的类型,因为它不会进行内存清理;为了使这项工作稳健地进行,您需要使用 std::string
s,然后您可以从中通过 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
)。