多态性和pybind11
Polymorphism and pybind11
当我想在python中使用C 多态性时,我对Pybind11有一个奇怪的行为。这是我问题的简单示例:
import polymorphism as plm
a = plm.mylist()
print(a)
a[0].print()
a[1].print()
此脚本的输出是
[mybase,mydedived]
mybase
mybase
但是预期的输出为
[mybase,mydedived]
mybase
mydedived
因为MyList返回一个std :: vector,其中包含一个派生类(MyDedived(的实例作为第二个成员。奇怪的是,当我整体打印列表时,我会识别mydedived。
这是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");
}
编辑:更令人惊讶的是,当我删除mydedived的"打印"的绑定时,我会收到以下错误消息
[mybase,mydedived]
mybase
追溯(最近的最新电话(:
文件" test.py",第8行,
a [1] .print((
attributeError:'polymorpormist.myderived的'对象没有属性'print'
此消息似乎意味着在调用错误版本的印刷版本时,MyDedived已得到认可(如果我理解很好(。
编辑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
编译并产生预期的输出。
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 shell:
>>> import example
>>> l = example.mylist()
>>> l[0].print()
MyBase::print()
>>> l[1].print()
MyDerived::print()
相关文章:
- 多态性和功能结合
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 使用取消引用的指针的多态性会产生意外的结果.为什么?
- C++boost序列化多态性问题
- 如何查找哪个类对象位于数组的特定索引上(多态性)
- 如何在多线程中正确使用unique_ptr进行多态性?
- 具有智能指针的多态性
- 在 C++ 中在堆栈上创建实例时如何保持多态性?
- 继承/多态性 - 我是否被迫使用"protected"变量?
- C++ 多态性在代码::块 17.12 中不起作用
- C++ 泛型和多态性:这种模式可行吗?
- 为什么我们实际上需要运行时多态性?
- 如何在这个简单的最小示例中实现多态性?
- 如何使用静态多态性在 int 和指针类型之间进行转换?
- 无法初始化已知大小的矢量指针,该大小不会因多态性而更改
- 运行时多态性和dynamic_cast需要澄清
- 如何调用指针类型的方法(禁用多态性)?
- 从基类调用函数的多态性
- 运行时多态性 - 箭头运算符访问了错误的成员?
- 多态性和pybind11