4

这是我的第一篇文章 :)。我可以将 python 扩展对象转换为 C++ 指针,但我有一个问题。首先,我将向您展示我的代码,然后我将解释问题所在。

这是我的课:

#include <boost/python.hpp>


using namespace boost::python;


class Base
{

public:

    virtual const char* HelloWorld() = 0;

};


class BaseWrapper : public Base, public wrapper<BaseWrapper>
{

public:

    virtual const char* HelloWorld()
    {

        if (override f = this->get_override("HelloWorld"))
            return call<const char*>(f.ptr());

        return "FAILED TO CALL";

    }

};

增强包装:

BOOST_PYTHON_MODULE(hello_ext)
{

     class_<Base, boost::noncopyable>("Base", no_init);

     class_<BaseWrapper, bases<Base> >("BaseWrapper")
         .def("HelloWorld", &BaseWrapper::HelloWorld);

}

Python代码(hello.py):

def NewDerived():
    import hello_ext

    class Derived(hello_ext.BaseWrapper):
        def __init__(self):
                super(Derived, self).__init__()
        def HelloWorld(self):
                return "This is a Hello World!!!"

    return Derived()

和主文件:

int main() 
{

     // Start the interpreter.
     Py_Initialize();

     // Import the module that we need (hello.py)
     object module = import("hello");

     // Get a C++ pointer of the derived python class.
     Base* base = extract< Base* >( module.attr("NewDerived")() );

     // Call the HelloWorld function
     std::cout << base->HelloWorld() << std::endl;

}

当我运行我的应用程序时,我可以在屏幕上看到“这是一个 Hello World !!!” 正如我所料。那么,有什么问题???假设我将 python 代码更改为:

def NewDerived():
    import hello_ext

    class Derived(hello_ext.BaseWrapper):
        def __init__(self):
                super(Derived, self).__init__()
        def HelloWorld(self):
                return "This is a Hello" # I CHANGED THIS LINE!!!!

    return Derived()

然后,当我再次运行我的应用程序时,它崩溃了,因为我在该行中遇到了一个错误:

std::cout << base->HelloWorld() << std::endl;

因为base是NULL。

更准确地说,错误是“访问冲突读取位置 0xblablabla”。当我调试时,调试器在函数处停止(我认为是 Boost 或 Python 代码)

inline api::object_base::~object_base()
{
    Py_DECREF(m_ptr);
}

你怎么看???

4

1 回答 1

2

最后,另一位程序员向我解释了解决方案。

我不知道它最初为什么起作用,但问题是在我尝试调用成员函数之前对象已被破坏。我需要将提取调用分成两部分,如下所示:

object derived = module.attr("NewDerived")();
Base* base = extract< Base* >( derived );

这将使对象保持足够长的时间,以便我实际调用它的函数。

于 2011-01-19T13:21:52.937 回答