怎样把Python嵌入Windows应用中
[文] Edward K<
[email protected]> [编译] FreeC
下面文件名中出现的'##'是被缩写的版本号.举例来说,Python 2.1.1,##将会被21替换.
在Windows应用中嵌入Python脚本解释器的方法可以汇总如下:
1.不要直接把Python建立在你的.exe文件中。在Windows中,Python应该以DLL的形式引入,从而可以使用Python的 DLL's。 (第一个要点)。应该连接到Python##.dll;它一般被安装在c:/Windows/system中。
你可以静态或动态地连接到Python。静态意味着要连接python15.lib。缺点是当Python##.dll不存在的时候你的应用程序将不能运行. 。
一般提示: Python##.lib是python##.dll对应的所谓"引入库",它仅仅为连接定义符号。
Borland提示:首先使用Coff2Omf.exe把Python##.lib转换成OMF格式。
动态连接简化了连接选项,因为一切都发生在运行时。你的代码必须用Windows函数LoadLibraryEx() 载入Python##.dll。你的代码也必须使用Windows函数GetProcAddress()获得指针,从而可以用它来操作 Python##.dll中的存取例程和数据(Python's C API's)。宏能够使那些指针透明地使用在任何调用Python's C API的C代码中。
2. 如果你使用SWIG(简化封装和接口生成器), 将能够容易地生成Python"扩充模块",它使得Python可以使用应用程序的数据和方法。 SWIG几乎会为你处理所有蹩脚的细节。结果是C代码连入你的 .exe 文件之内,你不必生成DLL文件,这样简化了联接。
3. SWIG将会产生一个初始化函数(C函数),它的名字和扩展模块的名字有关。 举例来说,如果模块的名是leo,init函数将会被称为initleo() 。如果你使用SWIG shadow类,init函数将会被称为initleoc(),这个初始化通常隐藏了shadow类使用的 helper 类。
你能在第2步连接C代码进入你的.exe文件的原因是这个初始化函数等于把模块引入Python中(第二个要点)。
4. 简而言之,你能使用下面的代码初始化Python解释器引人你的扩充模块。
#include "python.h"
...
Py_Initialize(); // Initialize Python.
initmyAppc(); // Initialize (import) the helper class.
PyRun_SimpleString("import myApp") ; // Import the shadow class.
5. 如果你使用了除MSVC以外的编译器,可能会有两个问题出现,编译器用来构建Python##.dll.
问题 1: 基于FILE*的所谓 "非常高层"的函数在多编译器环境中将不能正常工作;每个编译器对待FILE结构会有所不同。从实现的角度看他们是非常低层次的函数。
问题 2: 当生成对void函数的封装的时候 ,SWIG产生下面的代码:
Py_INCREF(Py_None);
_resultobj = Py_None;
return _resultobj;
Py_None 是和python##.dll中一个叫_Py_NoneStruct的复杂数据结构相关的宏,同样,这段代码也不能在多编译器环境工作,用下面的代码代替:
return Py_BuildValue("");
它可能是用SWIG的%typemap命令自动地改变的,虽然我还没有做这方面的工作。(我完全是SWIG新手)。
6. 使用Python shell脚本在你的Windows app的内部 搭建Python解释器窗口不是好的想法,因为产生的窗口将会独立于你的app的窗口系统。然而,你(或 wxPythonWindow类)应该创建一个"本地的"解释器窗口。它容易连接到到Python解释器。你可以重定向 Python的输入/输出到任何支持读写的对象,这样你全部的需要就是包含read()和write()方法的对象了(定义在你的扩充模块中)。