Проблема с указателем на объект Python для C ++ - PullRequest
4 голосов
/ 14 января 2011

это мой первый пост :). Я мог бы преобразовать расширенный объект 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». Когда я отлаживаюсь, отладчик останавливается на функции (думаю, Boost или Python)

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

Что вы думаете ???

1 Ответ

2 голосов
/ 19 января 2011

Наконец, другой программист объяснил мне решение.

Я не знаю, почему это сработало изначально, но проблема в том, что объект разрушается, прежде чем я пытаюсь вызвать функцию-член. Мне нужно разбить вызов извлечения на две части, например:

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

Это будет держать объект достаточно долго, чтобы я мог фактически вызывать на нем функции.

...