簡體   English   中英

boost :: python:將C ++類暴露給C ++應用程序中嵌入的python腳本

[英]boost::python: expose a C++ class to a python script embedded in a C++ app

我能夠成功加載python腳本文件並在C ++應用程序中使用boost::python來調用函數。

在Boost python EmbeddingPython Wiki中,有關於如何加載python模塊的提示

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"];
}

我可以成功地使用它導入python模塊( test.py

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;
}

使用hello-world test.py腳本運行上述代碼可以正常工作:

test.py:

def run():
    print "hello world"

輸出:

 hello world 

將C ++類暴露給python:

但是,我現在想向該腳本公開C ++類。

struct Foo
{
    void f() {}
};

根據boost::python文檔,我將此類公開如下:

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

按照上面鏈接的Wiki中的說明,然后我可以導入FooModule ,並將其存儲在我的globals

PyImport_AppendInittab("FooModule", &initFooModule); 

...

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

該導入是導入我的test.py腳本之前完成的,並且此globals對象是導入我的腳本時傳遞給bp::exec對象(即: Foo 應該位於bp::exec暴露給我的腳本的globals dict中。輸入)。

但是,由於某些原因, test.py 無法看到我的Foo模塊

題:

如何將我的Foo類暴露給我正在加載的test.py python腳本?


完整的工作示例:

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 

與其嘗試從C ++端將FooModule注入Python腳本, PyImport_AppendInittab從C ++端向PyImport_AppendInittab注冊模塊,然后從Python端import它:

import FooModule

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM