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;

}

アプリケーションを実行すると、「This is a 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);
}

どう思いますか???

4

1 に答える 1

2

最後に、別のプログラマーが解決策を説明してくれました。

なぜそれが最初に機能したのかはわかりませんが、問題は、メンバー関数を呼び出す前にオブジェクトが破棄されていることです。次のように、抽出呼び出しを 2 つの部分に分割する必要があります。

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

これにより、実際に関数を呼び出すのに十分な時間、オブジェクトが保持されます。

于 2011-01-19T13:21:52.937 に答える