- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
当我想在 Python 中使用 C++ 多态时,我对 pybind11 有一个奇怪的行为。这是我的问题的一个简单示例:
import polymorphism as plm
a = plm.mylist()
print(a)
a[0].print()
a[1].print()
这个脚本的输出是
[MyBase, MyDerived]
MyBase
MyBase
但预期的输出是
[MyBase, MyDerived]
MyBase
MyDerived
因为 mylist 返回一个 std::vector,它包含一个派生类 (MyDerived) 的实例作为第二个成员。奇怪的是,当我打印整个列表时,MyDerived 被识别出来。
这是C++代码的头文件:
/* polymorphism.hpp */
#ifndef POLYMORPHISM_HPP
#define POLYMORPHISM_HPP
#include <vector>
class MyBase
{
public:
virtual void print() const;
};
class MyDerived : public MyBase
{
public:
virtual void print() const;
};
std::vector<MyBase*> mylist();
#endif
这是cpp文件:
#include "polymorphism.hpp"
#include <iostream>
#include <pybind11/stl.h>
#include <pybind11/pybind11.h>
void MyBase::print() const
{ std::cout << "MyBase" << std::endl; }
void MyDerived::print() const
{ std::cout << "MyDerived" << std::endl; }
std::vector<MyBase*> mylist()
{
std::vector<MyBase*> list(2);
list[0] = new MyBase();
list[1] = new MyDerived();
return list;
}
PYBIND11_MODULE(polymorphism, m)
{
pybind11::class_<MyBase>(m, "MyBase")
.def(pybind11::init<>())
.def("print", &MyBase::print)
.def("__repr__", [](const MyBase &a) { return "MyBase"; });
pybind11::class_<MyDerived, MyBase>(m, "MyDerived")
.def(pybind11::init<>())
.def("print", &MyDerived::print)
.def("__repr__", [](const MyDerived &a) { return "MyDerived"; });
m.def("mylist", &mylist, "return a list");
}
编辑:更令人惊讶的是,当我删除 MyDerived 的“打印”绑定(bind)时,我收到以下错误消息
[MyBase, MyDerived]
MyBase
Traceback (most recent call last):
File "test.py", line 8, in
a[1].print()
AttributeError: 'polymorphism.MyDerived' object has no attribute 'print'
这条消息似乎意味着 MyDerived 被很好地识别,而调用了错误版本的打印(如果我理解得很好的话)。
编辑 2:这是一个使用蹦床类的版本。但是,此版本会导致相同的错误输出。
/* polymorphism.hpp */
#ifndef POLYMORPHISM_HPP
#define POLYMORPHISM_HPP
#include <vector>
#include <pybind11/stl.h>
#include <pybind11/pybind11.h>
class MyBase
{
public:
virtual void print() const;
};
class MyDerived : public MyBase
{
public:
virtual void print() const;
};
std::vector<MyBase*> mylist();
class PyMyBase : public MyBase
{
public:
using MyBase::MyBase; // Inherit constructors
void print() const override { PYBIND11_OVERLOAD(void, MyBase, print ); }
};
class PyMyDerived : public MyDerived
{
public:
using MyDerived::MyDerived; // Inherit constructors
void print() const override { PYBIND11_OVERLOAD(void, MyDerived, print);}
};
#endif
对应的cpp文件如下:
/* polymorphism.cpp */
#include "polymorphism.hpp"
#include <iostream>
void MyBase::print() const
{ std::cout << "MyBase" << std::endl; }
void MyDerived::print() const
{ std::cout << "MyDerived" << std::endl; }
std::vector<MyBase*> mylist()
{
std::vector<MyBase*> list(2);
list[0] = new MyBase();
list[1] = new MyDerived();
return list;
}
PYBIND11_MODULE(polymorphism, m)
{
pybind11::class_<MyBase, PyMyBase>(m, "MyBase")
.def(pybind11::init<>())
.def("print", &MyBase::print)
.def("__repr__", [](const MyBase &a) { return "MyBase"; });
pybind11::class_<MyDerived, PyMyDerived>(m, "MyDerived")
.def(pybind11::init<>())
.def("print", &MyDerived::print)
.def("__repr__", [](const MyDerived &a) { return "MyDerived"; });
m.def("mylist", &mylist, "return a list");
}
最佳答案
我不知道为什么,但是 pybind11
mylist()
中的原始指针似乎有问题.如果将返回类型更改为 vector<unique_ptr<MyBase>>
,该示例将正常工作.以下示例编译为 python 模块 example
并产生预期的输出。
示例.cpp:
#include <pybind11/stl.h>
#include <pybind11/pybind11.h>
#include <iostream>
#include <memory>
#include <vector>
class MyBase {
public:
virtual void print() const {
std::cout << "MyBase::print()" << std::endl;
}
};
class MyDerived : public MyBase {
public:
virtual void print() const override {
std::cout << "MyDerived::print()" << std::endl;
}
};
std::vector<std::unique_ptr<MyBase>> mylist() {
std::vector<std::unique_ptr<MyBase>> v;
v.push_back(std::make_unique<MyBase>());
v.push_back(std::make_unique<MyDerived>());
return v;
}
PYBIND11_MODULE(example, m) {
pybind11::class_<MyBase>(m, "MyBase")
.def(pybind11::init<>())
.def("print", &MyBase::print)
.def("__repr__", [](MyBase const&) { return "MyBase"; });
pybind11::class_<MyDerived>(m, "MyDerived")
.def(pybind11::init<>())
.def("print", &MyDerived::print)
.def("__repr__", [](MyDerived const&) { return "MyDerived"; });
m.def("mylist", &mylist, "returns a list");
}
python 外壳:
>>> import example
>>> l = example.mylist()
>>> l[0].print()
MyBase::print()
>>> l[1].print()
MyDerived::print()
关于python - 多态性和pybind11,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49633990/
我来自 Asp.Net 世界,试图理解 Angular State 的含义。 什么是 Angular 状态?它类似于Asp.Net中的ascx组件吗?是子页面吗?它类似于工作流程状态吗? 我听到很多人
我一直在寻找 3 态拨动开关,但运气不佳。 基本上我需要一个具有以下状态的开关: |开 |不适用 |关 | slider 默认从中间开始,一旦用户向左或向右滑动,就无法回到N/A(未回答)状态。 有人
我是一名优秀的程序员,十分优秀!