简体   繁体   English

Boost Python:无法调用C ++虚拟函数,该函数在Python派生类中被覆盖

[英]Boost Python: Fails to call a C++ virtual function, which is overridden in a Python derived class

I have a Python class, which is derived from a C++ class and overrides part of the functions. 我有一个Python类,它是从C ++类派生的,并且覆盖了部分函​​数。 A C++ function receives an object of the Python class and stores it in a vector, so the Python class should not be collected by the GC. C ++函数接收Python类的对象并将其存储在向量中,因此GC不应收集Python类。 I tried two different approaches, but first one doesn't compile and second doesn't see the overrides at run time (the functions of C++ are called instead of the Python class functions). 我尝试了两种不同的方法,但是第一种方法不编译,第二种方法在运行时看不到重写(调用C ++函数而不是Python类函数)。 Please tell me what is the right way to do this. 请告诉我什么是正确的方法。

The C++ code: C ++代码:

class MyClass
{
public:
    virtual void PureVirtual(int i) = 0;
    virtual const char* VirtualWithDefaultImpl()
    {
        return "MyClass";
    }
};

void MyFnc(boost::shared_ptr<MyClass> obj)
{
    myVector.push_back(obj);
    std::cout << obj->VirtualWithDefaultImpl() << std::endl;
    obj->PureVirtual(0);
}

The python wrapper: python包装器:

class MyClassWrap : public MyClass, wrapper<MyClass>
{
public:
    MyClassWrap(PyObject* self) : m_self(self)
    {
        Py_INCREF(self);
    }
    MyClassWrap(PyObject* self, const MyClass& other) : MyClass(other), m_self(self)
    {
        Py_INCREF(self);
    }
    ~MyClassWrap()
    {
        Py_DECREF(m_self);
    }
    virtual void PureVirtual(int i)
    {
        this->get_override("PureVirtual")(i);
    }
    virtual const char* VirtualWithDefaultImpl()
    {
        if (override f = this->get_override("VirtualWithDefaultImpl"))
            return f();
        return MyClass::VirtualWithDefaultImpl();
    }
    const char* DefaultVirtualWithDefaultImpl()
    {
        return this->MyClass::VirtualWithDefaultImpl();
    }
private:
    PyObject* m_self;
};

BOOST_PYTHON_MODULE(MyModule)
{
    // First approach:
    // Fails in compilation with error C2243: 'type cast' : conversion from
    // 'MyClassWrap *' to 'boost::python::wrapper<T> *' exists, but is inaccessible
    //class_<MyClassWrap, boost::shared_ptr<MyClassWrap>, boost::noncopyable>("MyClass")

    // Second approach:
    // Doesn't see the overrides at runtime
    class_<MyClass, boost::shared_ptr<MyClassWrap>, boost::noncopyable>("MyClass")
        .def("PureVirtual", pure_virtual(&MyClass::PureVirtual), args("i"))
        .def("VirtualWithDefaultImpl", &MyClass::VirtualWithDefaultImpl,
            &MyClassWrap::DefaultVirtualWithDefaultImpl);
    def("MyFnc", &MyFnc, args("obj"));
}

The Python code: Python代码:

class PythonDerived(MyModule.MyClass):
    def PureVirtual(self, i):
        print i

    def VirtualWithDefaultImpl(self):
        return 'PythonDerived'

MyModule.MyFnc(PythonDerived())

Output of the second approach run. 运行第二种方法的输出。 As you can see the functions of MyClass are called instead of the PythonDerived functions: 如您所见,调用了MyClass的函数而不是PythonDerived函数:

MyClass

File "z:\tmp\tmp.py", line 11, in <module>
  MyModule.MyFnc(PythonDerived())

TypeError: 'NoneType' object is not callable

I have modified your wrapper class and how it is exposed to python and now that is working as expected: 我已经修改了您的包装器类,以及如何将其暴露给python,现在可以按预期运行:

class MyClassWrap : public MyClass, public python::wrapper<MyClass>
{
public:
    MyClassWrap() : MyClass()
    {
    }

    virtual void PureVirtual(int i)
    {
        this->get_override("PureVirtual")(i);
    }
    virtual const char* VirtualWithDefaultImpl()
    {
        if (python::override f = this->get_override("VirtualWithDefaultImpl"))
            return f();
        return MyClass::VirtualWithDefaultImpl();
    }
    const char* DefaultVirtualWithDefaultImpl()
    {
        return this->MyClass::VirtualWithDefaultImpl();
    }

};

BOOST_PYTHON_MODULE(MyModule)
{
python::class_<MyClassWrap, boost::shared_ptr<MyClassWrap>, boost::noncopyable>("MyClass")
    .def("PureVirtual", python::pure_virtual(&MyClassWrap::PureVirtual), python::args("i"))
    .def("VirtualWithDefaultImpl", &MyClassWrap::VirtualWithDefaultImpl,
         &MyClassWrap::DefaultVirtualWithDefaultImpl);
    python::def("MyFnc", &MyFnc, python::args("obj"));
}

Output: 输出:

PythonDerived
0

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C++:如何在不知道派生class的情况下调用虚拟function的派生(覆盖)function? - C++: How to call the derived (overridden) function of a virtual function without knowing the derivative class? 通过Python BOOST使用派生类(C ++) - Using derived class (C++) by Python BOOST How a friend function of a base class is calling the overridden virtual function of derived class even though they are private?(C++) - How a friend function of a base class is calling the overridden virtual function of derived class even though they are private ?(C++) 在派生类C ++中避免“纯虚函数调用” - Avoiding “Pure Virtual Function Call” in Derived Class C++ 在Boost python中提取C ++派生的类对象 - Extract c++ derived class object in boost python 使用 Boost.python 覆盖 Python 中的 C++ 虚拟函数? - override a C++ virtual function within Python with Boost.python? 扩展通过Boost.Python公开的虚拟C ++类 - Extending a virtual C++ class exposed via Boost.Python C++:调用派生的class的虚拟function - C++: Calling the virtual function of the derived class C++ 在派生的 ZA2F2ED4F8EBC4CBB4C21A2DDC9 中从虚拟 function 调用非虚拟 function - C++ call a non virtual function from virtual function in derived class 虚拟和派生的C ++类导出到Python - virtual and derived C++ classes exported to Python
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM