2016-12-06 11 views
4

C++アプリケーションでboost::pythonを使用してPythonスクリプトファイルを読み込んで関数を呼び出すことができました。boost :: python:C++アプリケーションをC++アプリケーションに埋め込まれたPythonスクリプトに公開する

ブーストのpython EmbeddingPython wikiには、how to load a python moduleというヒントがあります。

テストを:

namespace bp = boost::python; 

bp::object import(const std::string& module, const std::string& path, bp::object& globals) 
{ 
    bp::dict locals; 
    locals["module_name"] = module; 
    locals["path"]  = path; 

    bp::exec("import imp\n" 
      "new_module = imp.load_module(module_name, open(path), path, ('py', 'U', imp.PY_SOURCE))\n", 
      globals, 
      locals); 

    return locals["new_module"]; 
} 

私は正常

int main() 
{ 
    Py_Initialize(); 

    bp::object main = bp::import("__main__"); 
    bp::object globals = main.attr("__dict__"); 
    bp::object module = import("test", "test.py", globals); 
    bp::object run  = module.attr("run"); 

    run(); 

    return 0; 
} 

こんにちは、世界で上記のコードを実行するtest.pyスクリプトが正常に動作Pythonモジュール(test.py)をインポートするためにこれを使用することができます。 py:

def run(): 
    print "hello world" 

出力:パイソンのC++クラスの公開

hello world 

はしかし、私は今、そのスクリプトにC++クラスを公開します。 boost::pythonドキュメントを1として

struct Foo 
{ 
    void f() {} 
}; 

、次のように私は、このクラスを公開:上記のリンクウィキ内の命令を1として

BOOST_PYTHON_MODULE(FooModule) 
{ 
    bp::class_<Foo>("Foo") 
     .def("f", &Foo::f) 
     ; 
} 

を、私はその後、私のFooModuleをインポートして、私の中でそれを保存することができますglobals

PyImport_AppendInittab("FooModule", &initFooModule); 

... 

bp::object Foo = bp::import("FooModule"); 
globals["Foo"] = Foo; 

このインポートは私をインポートする前にをやっていますこのglobalsオブジェクトは、スクリプトをインポートするときにbp::execに渡されるものです(つまり、Fooになる必要があります)。bp::execはインポート時にスクリプトに公開されます。

しかし、何らかの理由で私のFooモジュールがない見え

test.pyにある質問:

どのように私はロードしていますtest.py Pythonスクリプトに私のFooクラスを公開することができますか?


全作業例:

test.py

def run(): 
    foo = Foo() 
    foo.f() 

main.cpp

#include <iostream> 
#include <boost/python.hpp> 

namespace bp = boost::python; 

bp::object import(const std::string& module, const std::string& path, bp::object& globals) 
{ 
    bp::dict locals; 
    locals["module_name"] = module; 
    locals["path"]  = path; 

    bp::exec("import imp\n" 
      "new_module = imp.load_module(module_name, open(path), path, ('py', 'U', imp.PY_SOURCE))\n", 
      globals, 
      locals); 
    return locals["new_module"]; 
} 

struct Foo 
{ 
    void f() {} 
}; 

BOOST_PYTHON_MODULE(FooModule) 
{ 
    bp::class_<Foo>("Foo") 
     .def("f", &Foo::f) 
     ; 
} 

int main() 
try 
{ 
    PyImport_AppendInittab("FooModule", &initFooModule); 
    Py_Initialize(); 

    // get a handle to the globals dict  
    bp::object main = bp::import("__main__"); 
    bp::object globals = main.attr("__dict__"); 

    // import FooModule, and store it in the globals dict 
    bp::object Foo = bp::import("FooModule"); 
    globals["Foo"] = Foo; 

    // import the test script, passing the populated globals dict 
    bp::object module = import("test", "test.py", globals); 
    bp::object run = module.attr("run"); 

    // run the script 
    run(); 

    return 0; 
} 
catch(const bp::error_already_set&) 
{ 
    std::cerr << ">>> Error! Uncaught exception:\n"; 
    PyErr_Print(); 
    return 1; 
} 

Output

>>> Error! Uncaught exception: 
Traceback (most recent call last): 
    File "test.py", line 2, in run 
    foo = Foo() 
NameError: global name 'Foo' is not defined 

答えて

1

だけではなく、Pythonの側からそれをC++側からPyImport_AppendInittabでモジュールを登録してからimport、C++側からPythonスクリプトにFooModuleを注入しようとしている:に

import FooModule 

def run(): 
    foo = FooModule.Foo() 
    foo.f() 
+0

注意上記を行う際に、これを見ている人は、 'bp :: import(" FooModule ");'はもう必要ありません。 'PyImport_AppendInittab'への呼び出しは、スクリプトが' FooModule'をインポートするために必要なものです。 –

関連する問題