2011-01-14 87 views
4

这是我的第一篇文章:)。我可以将python扩展对象转换为C++指针,但是我遇到了问题。首先我会告诉你我的代码,然后我会解释这个问题。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; 

因为基地是NULL。

更准确地说,错误是“访问冲突读取位置0xblablabla”。 当调试时,debugguer在功能停止(升压或Python代码,我认为)

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

你觉得呢???

回答

2

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

我不知道它为什么最初工作,但问题是,在我尝试调用成员函数之前,对象被破坏。我需要打破提取呼叫分为两个部分,像这样:

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

这将保持对象足够长的时间让我真正调用它的功能。