3

最初に言わなければならないのは、Python プログラマーとして、この問題を間違った視点から見ている可能性があるということです。大学時代に最後の C++ コードを書いてから何年も経ちました。

firebreath を使用してハイブリッド python/c++ プラグインを作成しようとすると、少し問題が発生します。これまでのところ、boost/python.h を使用してすべてのパーツを統合することに成功していますが、python 内からイベントを発生させようとすると問題が発生しました。Python 関数と C++ 関数を (BOOST_PYTHON_MODULE を使用して) バインドする必要があるという問題に遭遇しました。最初に、Python を JSAPI 派生クラス fbtestconpythonAPI に直接バインドしようとしましたが、このアプローチの問題は、ブラウザーによってインスタンス化された JSAPI オブジェクトへの参照がないことのようで、Python 関数と同等の C++ の間であらゆる種類の署名の不一致の問題が発生します。実行時間。

これを修正するために私に起こった唯一のこと(同意します、醜い汚い解決策です)は、set_pluginPointerで手動で初期化するグローバルポインターを使用することです。これは実際にはこれまでのところかなりうまく機能していますが、正しい方法ではないことはわかっています。JSAPI オブジェクトで「生の」ポインタを使用してはならないことを読みましたが、この特定の実装でそれを shared_ptr に置き換える方法がわかりません。もう 1 つの問題は、すべてのインスタンスで共有されるグローバル変数です。たとえば、最後に開いたタブ/ウィンドウですべてのイベントが発生します。後者を解決する 1 つの方法は、インデックスが現在のウィンドウ/スレッド ID であるある種の配列を作成することです。これは、JSAPI オブジェクトと python/c++ 関数の両方からアクセスできるはずです。

もちろん、私はオープンであり、この特定の回避策を改善/修正する方法、またはハッキングせずに boost::python と firebreath を通信する正しい方法についての提案を非常に高く評価します。

以下は、プラグインコードの関連部分です

// Global pointer to plugin instance
fbtestconpythonAPI *fbtestPtr;
void fbtestconpythonAPI::set_pluginPointer(const std::string& val){
    m_testString = val;
    fbtestPtr = this; //Global pointer initialization
}

void echo(std::string x){
    // Firing the echo event on the plugin instance using the global raw pointer
    fbtestPtr->fire_echo(x, 1);
}

BOOST_PYTHON_MODULE(Pointless) {
    def("echo", echo);
}

FB::variant fbtestconpythonAPI::echo(const FB::variant& msg){
    int result_value;
    Py_Initialize(); 

    try {
        initPointless(); // initialize Pointless

        PyRun_SimpleString("import Pointless");
        PyRun_SimpleString("Pointless.echo('hello world')");

        object module(handle<>(borrowed(PyImport_AddModule("__main__"))));
        object dictionary = module.attr("__dict__");
    } catch (error_already_set) {
        PyErr_Print();
    }

    Py_Finalize();
    return 0;
}
4

1 に答える 1

1

簡単に見ると、次のようにクラスをエクスポート用にセットアップします。

class_<YourAPI, boost::noncopyable>("YourAPI", no_init)
    .def("function", &YourAPI::function);

次に、C++ インスタンスへの参照を Python に渡すことができます。これにより、関数を呼び出してイベントを発生させることができます。

于 2012-02-17T00:58:44.890 に答える