在Python中暴露C++函数并在C++中嵌入Python
我的应用程序有一些事件,每个事件可以有一些动作。这些动作是用C++实现的。我想把这些核心功能暴露给Python,让Python来编写这些动作。这样做的好处是我可以在不重新编译的情况下修改动作。例如:
CppClass o;
// --- this is a action----
o.f1();
o.f2();
// ------------------------
用Python来编写动作脚本:
def action1(o):
o.f1()
o.f2()
在C++中,使用解释器来运行这个脚本,找到action1并用一个从C++对象转换过来的PyObject来调用它。实际上,我并没有把f1()和f2()暴露给Python,我只是用Python重新组织了动作的定义,所有的功能都是通过C++的二进制代码来运行的。注意,我不需要在Python中给f1()和f2()提供定义。
现在的问题是:我该如何暴露全局函数呢?比如:
def action2():
gf1()
gf2()
boost::python可以暴露函数,但它有点不同,它需要编译一个DLL文件,并且main()属于Python脚本。当然,我可以把全局函数做成类的静态成员,但我只是想知道一下。注意,我必须在Python中给gf1()和gf2()提供定义。
Jython可以很简单地做到这一点:只需在Python代码中导入Xxx,然后调用Xxx.gf1()就可以了。但是在Cython中,我该如何在Python中定义gf1()呢?这是一种扩展,但扩展要求Xxx提前编译。看起来唯一的办法就是把gf()放进一个类里?
3 个回答
ffpython是一个C++库,它封装了Python 2.x的接口。查看代码库
调用Python函数的方法是:ffpython.call("fftest", "test_stl", a1, a2, a3);
注册C++类:
ffpython.reg_class<foo_t, PYCTOR(int)>("foo_t")
.reg(&foo_t::get_value, "get_value")
.reg(&foo_t::set_value, "set_value")
.reg(&foo_t::test_stl, "test_stl")
.reg_property(&foo_t::m_value, "m_value");
你可能还想看看 Cython。
Cython的主要功能是把(部分)Python代码转换成C或C++代码,从而构建原生的Python扩展。这意味着你可以用一种简洁且类似Python的语法来和C/C++代码进行交互。
Cython的用户指南提供了一个很好的例子,展示了如何从Python调用一个简单的C++类:http://docs.cython.org/src/userguide/wrapping_CPlusPlus.html#declaring-a-c-class-interface
除了创建扩展,Cython还可以生成嵌入Python解释器的C/C++代码,这样你就不需要构建和分发一个外部的DLL。详细信息请查看:http://wiki.cython.org/EmbeddingCython
解决了。boost::python的文档真的是很差劲……
举个例子:暴露函数
void ff(int x, int y)
{
std::cout<<x<<" "<<y<<std::endl;
}
给Python用:
import hello
def foo(x, y)
hello.ff(x, y)
你需要把它作为一个模块暴露出来:
BOOST_PYTHON_MODULE(hello)
{
boost::python::def("ff", ff, boost::python::arg("x"), boost::python::arg("y"));
}
但这仍然不是一个“全局函数”,所以要把它暴露到Python的主作用域:
BOOST_PYTHON_MODULE(__main__)
{
boost::python::def("ff", ff, boost::python::arg("x"), boost::python::arg("y"));
}
然后你就可以写:
def foo(x, y)
ff(x, y)