pybind11 虚函数的未定义行为

问题描述 投票:0回答:1

我正在尝试使用一个简单的虚函数,但遇到了一些奇怪的问题,看起来像是未定义的行为。我已经从代码中删除了所有内容以重现问题:

#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);
c++ virtual pybind11
1个回答
0
投票

正如 @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
都可以工作,不确定是否有区别。

© www.soinside.com 2019 - 2024. All rights reserved.