【问题标题】:Python to C++: From Deriv, to Base, to Deriv againPython 到 C++:从 Deriv 到 Base,再到 Deriv
【发布时间】:2011-07-29 11:53:18
【问题描述】:

我正在使用 Boost.Python 将我的 C++ 代码公开给 Python。我遇到了与将对象从一种语言多次传递到另一种语言有关的困难。这是我想做的:

C++ 代码

class Base
{
  public:
    void baseTest() {
        std::cout << "Base::basetest()";
    }
};

class Deriv
    : public Base
{
  public:
    void derivTest() {
        std::cout << "Deriv::derivTest()";
    }
};

void call(Base& b, boost::python::object func)
{
    func(b);
}

BOOST_PYTHON_MODULE(event)
{
    using namespace boost;
    using namespace boost::python;

    class_<Base>("Base")
        .def("baseTest", &Base::baseTest)
    ;

    class_<Deriv, bases<Base>>("Deriv")
        .def("derivTest", &Deriv::derivTest)
    ;

    def("call", call);
}

Python 代码

from event import *

def callback(deriv):
    deriv.baseTest() # works fine
    deriv.derivTest() # crash!

def run():
    d = Deriv()
    call(d, callback)

我想要发生的事情

  1. C++:调用 Python 中定义的 run() 函数。 (这里没问题)

  2. Python:run() 创建一个新的Deriv 对象;它通过call 函数将它和一个函数对象callback 传递回C++。 (也可以)

  3. C++:call()Deriv 对象作为Base&amp;。它将 Base-reference 传递给它通过第二个参数接收到的 Python 回调。

  4. Python:回调从 C++ 接收 Base 对象。但是,它希望它是Deriv:如果我调用derivTest(),程序就会崩溃。但是,如果我调用baseTest(),它不会崩溃。

如何让回调不崩溃?

【问题讨论】:

  • 也许(我不太确定),你应该将baseTest设为虚拟(并添加一个虚拟析构函数)。
  • baseTest 不需要是虚拟的,因为它没有被覆盖。
  • @Alexandre, Mike:将baseTest 虚拟化确实没有意义。添加 anything 虚拟(可能应该是析构函数)可能会有所帮助,因为拥有虚拟方法允许 C++ 运行时检查运行时类型。
  • @Jan:哦,我读得太快了……但是,我最初的想法是 RTTI 是不可能的,因为你的类不是多态的(因此崩溃)。但是您会收到一条编译器消息。

标签: c++ python boost


【解决方案1】:

感谢 cmets,我找到了解决方案。这实际上很简单,您只需将 Base 对象包装在 shared_ptr 中,而不是通过引用传递它,如下所示:

void call(boost::shared_ptr<Base> b, boost::python::object func)
{
    func(b);
}

但是要小心一些事情。我尝试使用 Visual C++ 2010 Express 附带的 std::shared_ptr (“内存”标头),但它导致了崩溃。我必须使用 boost::shared_ptr 才能工作。 (我使用的是 1.46.1 版本的 Boost。)

【讨论】:

    猜你喜欢
    • 2017-03-20
    • 2012-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多