首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >包装pybind11重载方法的python参数

包装pybind11重载方法的python参数
EN

Stack Overflow用户
提问于 2022-02-15 10:12:14
回答 2查看 193关注 0票数 1

我正在尝试为一些遗留的C++代码创建python绑定,这些代码实现了它自己的“扩展”字符串类aString,它广泛使用该类。这对于.def(py::init<const std::string &, int>())来说很好,但是一旦我尝试包装重载的方法,pybind11就不会自动将std::string转换为aString。MWE从pybind11文档中改编而来:

src/example.cpp

代码语言:javascript
复制
#include <pybind11/pybind11.h>

// Extended string class and struct in legacy library
class aString : public std::string
{
public:
    aString() : std::string() {}
    aString(const char *str) : std::string(str) {}
    aString(const std::string &str) : std::string(str) {}
};

struct Pet
{
    Pet(const aString &name, int age) : name(name), age(age) {}

    void set(int age_) { age = age_; }
    void set(const aString &name_) { name = name_; }

    aString name;
    int age;
};

// Python bindings
namespace py = pybind11;

PYBIND11_MODULE(example, m)
{
    py::class_<aString>(m, "aString")
        .def(py::init<const std::string &>())
        .def("__repr__",
             [](const aString &a)
             {
                 return "<aString ('" + a + "')>";
             });

    py::class_<Pet>(m, "Pet")
        .def(py::init<const std::string &, int>())
        .def("set", static_cast<void (Pet::*)(int)>(&Pet::set), "Set the pet's age")
        .def("set", static_cast<void (Pet::*)(const aString &)>(&Pet::set), "Set the pet's name")
        .def("__repr__",
             [](const Pet &a)
             {
                 return "<Pet ('" + a.name + "')>";
             });
    ;
}

CMakeLists.txt

代码语言:javascript
复制
cmake_minimum_required(VERSION 3.4)
project(example)
add_subdirectory(pybind11)
pybind11_add_module(example src/example.cpp)

在python中,以下功能很好:

代码语言:javascript
复制
import example
p = example.Pet("Penny", 1)
p.set(3)
a = example.aString("Anne")
p.set(a)

但是,以下消息失败:

代码语言:javascript
复制
#> p.set("Jenny")
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-9-c5b0ff7c5315> in <module>
----> 1 p.set("Jenny")

TypeError: set(): incompatible function arguments. The following argument types are supported:
    1. (self: example.Pet, arg0: int) -> None
    2. (self: example.Pet, arg0: example.aString) -> None

Invoked with: <Pet ('Anne')>, 'Jenny'

我尝试将我的pybinding改为.def("set", static_cast<void (Pet::*)(const std::string &)>(&Pet::set), "Set the pet's name"),而不是aString,但这不会编译,因为std::string不是重载实例之一。我不能在std:string库中为C++添加额外的重载实例。

我希望能够调用p.set("Jenny"),让pybind11将"Jenny"转换为aString("Jenny"),而不是p.set(example.aString("Jenny"))。这是我与pybind11的第一个项目,所以任何帮助都将不胜感激,谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-02-15 14:01:45

通过添加以下语句,可以在类型之间启用隐式转换

代码语言:javascript
复制
py::implicitly_convertible<std::string, aString>();

通常,只有当(在您的情况下) py::implicitly_convertible<A, B>()有一个以A作为其唯一参数的构造函数时,B才能工作。

票数 1
EN

Stack Overflow用户

发布于 2022-02-15 22:12:54

我已经将@it 1985的答案标记为正确,因为这是我最简单的解决方案--我不需要为每个方法调用手动将每个std::string转换为aString

但是,如果任何人必须包装或添加另一种类型的重载,我确实想出了一个解决方案:

代码语言:javascript
复制
py::class_<Pet>(m, "Pet")
    // ...
    .def("set",
        [](Pet &self, const std::string &s)
        {
            aString as = aString(s);
            self.set(as);
        });
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71124629

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档