如何让一个复杂的C++程序可用Python和/或Lua脚本化?
我现在面临一个任务,就是让一个C++应用程序可以被用户编写脚本。这个应用已经开发了好几年,之前没人考虑过这个问题。它包含了很多高级功能,比如多线程、模板技巧和多重继承。我们希望使用Python作为脚本语言,但如果Lua更容易实现,也可以考虑Lua。
问题 1
根据我目前了解到的,主要有两种方法可以把Python或Lua和C++结合起来:一种是“扩展”,另一种是“嵌入”。
在这种情况下,我似乎需要两者结合。脚本语言需要访问应用程序中的对象、方法和数据,但在用户编写完脚本后,应用程序需要能够调用这些脚本,而不需要重启任何东西。
在现实世界中,通常是怎么做到的呢?
问题 2
网上有很多手动解决方案和绑定生成器,种类繁多,但都不太完美。
- swig, pyste, Py++, ctypes, Boost.Python sip, PyCXX, pybindgen, robin, (Cython/Pyrex, Weave)
- CppLua, Diluculum, Luabind, Luabridge, LuaCpp, Luna/LunaWrapper, MLuaBind, MultiScript, OOLua, SLB, Sweet Lua, lux (这个列表来自lua wiki)
- CPB, tolua, tolua++, toLuaxx, luna,还有swig
网上对这些工具的评论大多有点过时。例如,有人说swig在处理复杂情况时很难用,并且生成的代码难以理解。另一方面,它最近更新到了2.0版本。
上述一些工具使用pygccxml来让gcc分析C++代码,然后生成绑定。我觉得这个主意不错,因为gcc可能比我更懂代码 :-)。这个方法效果好吗?
如果我测试所有这些工具,可能会花掉我整个项目一半的时间。
所以,你们推荐哪几个呢?
5 个回答
关于第一个问题 - 是的,你需要做两件事。
你需要把你的应用程序的脚本接口暴露给一个嵌入式解释器,这样它就可以运行用户的脚本了。
Python的手册中有关于嵌入的部分,其中包括一个关于 扩展嵌入式Python 的章节,还有一些类似的Lua教程,比如 这篇文章。当然,当你决定使用哪种脚本语言和绑定机制时,可能会找到更简单的方法。
上面提到的一些方法使用了pygccxml,让gcc来分析C++代码,然后生成绑定代码。我觉得这个主意挺不错的,因为gcc可能比我更懂这些代码 :-)。这个方法效果好吗?
类似的方法也在Lua Qt绑定中使用 - lqt。它使用cpptoxml
来生成一个XML文件,这个文件包含了所有的类和方法以及它们的参数,然后根据这个文件生成C++绑定代码。
这个方法效果很好,生成器几乎可以绑定所有的Qt类和方法,包括虚方法、重载的操作符、特定的模板类、信号/槽机制等等。
虽然这个工具是专门为Qt创建的,但它还有一个“noqt”模式,可以作为通用的绑定工具。不幸的是,我没有使用过这个模式,所以不太清楚绑定你的代码需要多少工作量。
我不太推荐使用swig,因为在复杂的情况下,它生成的绑定效果很难令人满意:我有过这样的经历。我不得不写一个糟糕的脚本,去“解析”原始的C++代码,以生成一些swig能处理的、可以接受的C++代码,从而生成合适的绑定。所以,总的来说:尽量避免任何依赖于解析原始C++程序的解决方案。
在Lua和Python之间:我发现Lua的文档要好得多,实施也更干净。Python有一个全局锁(GIL),而Lua则可以在每个线程中有一个解释器实例。例如,如果你可以选择的话,我会推荐Lua。它是一个更小的语言,更容易理解,更容易嵌入(API更简洁小巧,文档也非常优秀)。我在一个小项目中使用过luabind,觉得它很好用。