我正在尝试使用一个简单的虚函数,但遇到了一些奇怪的问题,看起来像是未定义的行为。我已经从代码中删除了所有内容以重现问题:
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
namespace py = pybind11;
struct vec3
{
double t, x, y;
vec3(double t, double x, double y) : t(t), x(x), y(y) {}
};
class Point : public vec3
{
public:
Point(double t, double x, double y) : vec3(t, x, y) {}
virtual void test() {} // if this is virtual the problem occurs!
};
PYBIND11_MODULE(relatpy, m)
{
py::class_<vec3>(m, "vec3")
.def(py::init<double, double, double>())
.def_readwrite("t", &vec3::t)
.def_readwrite("x", &vec3::x)
.def_readwrite("y", &vec3::y);
py::class_<Point, vec3, PyPoint>(m, "Point")
.def(py::init<double, double, double>());
}
虚拟函数
test
不执行任何操作,但如果我删除virtual
,问题就会消失。我不知道为什么会发生这种情况,但是当我运行以下 python 代码时:
from relatpy import *
p = Point(1, 2, 3) # t x y
print(p.t)
print(p.x)
print(p.y)
# should print 1 2 3 but prints JUNK 1 2
正如评论所说,我期望 1, 2, 3,但得到一些垃圾,1, 2。 编辑:正如 @273K 在评论中指出的,这个 JUNK 是 vtable 指针,尽管我不确定为什么它最终出现在
t
变量中。因此,我们非常感谢任何有关如何解决此问题的帮助!
我期望输出 1 2 3 但只有当
test
是 virtual
时我才会得到“JUNK, 1, 2”。我尝试实现一个实现了 virtual void test
的蹦床类,但这似乎并没有解决问题。无论如何,这是代码,以防我做错了什么:
蹦床课
class PyPoint : public Point
{
public:
/* Inherit the constructors */
using Point::Point;
/* Trampoline (need one for each virtual function) */
void test() override { PYBIND11_OVERRIDE_PURE(void, Point, test); }
};
以及我更改的绑定:
py::class_<Point, vec3, PyPoint>(m, "Point")
.def(py::init<double, double, double>())
.def("test", &Point::test);
正如 @273K 在评论中建议的那样,我必须在 de pybind 绑定中添加 t、x、y,如下所示:
py::class_<Point, vec3, PyPoint>(m, "Point")
.def(py::init<double, double, double>())
.def("test", &Point::test);
.def_readwrite("t", &Point::t)
.def_readwrite("x", &Point::x)
.def_readwrite("y", &Point::y);
似乎
&Point::t
和&vec3::t
都可以工作,不确定是否有区别。