[工程疑难]windows版的gvim不能补全wxPython的问题

这个问题困扰我许久,终于解决了。

 

首先,在python解释器中直接import wx,是没有问题的,能够正常使用wxPython,说明安装wxPython成功了的。

但是,打开gvim,编辑一个.py文件,在脚本中import wx,声明一个变量app = wx.App(),再键入app.,结果没有弹出自动补全菜单。

要知道,面向对象gui库十分庞大,不太可能去记类的方法,因此,自动补全所提供的列表,非常重要。

 

gvim对python的自动补全支持在文件pythoncomplete.vim中实现,浏览一下知道,补全功能依赖于动态语言的反射(eval、dir),如果该功能有问题的话,调用python函数showdbg就可以调查。

好,在gvim的命令栏键入:

:py showdbg()

从其中的信息可以得知,gvim内置的python解释器在import wx时失败了。

再在gvim中测试一下:

:py import wx

提示import _core_时找不到模块。

 

用ollydbg附加到gvim中,发现python用LoadLibraryEx(参数LOAD_WITH_ALTERED_SEARCH_PATH)加载_core_.pyd,结果失败了,Win32错误码为ERROR_MOD_NOT_FOUND。自己写一个C++测试程序(使用的vc版本应该和编译wxPython的vc版本相同),用同样的参数调用LoadLibraryEx,却能成功。

 

总之,到这里,确认gvim不能自动补全的原因是gvim内置的python解释器import wx失败,而后者import wx失败又是因为windows在用LoadLibraryEx加载_core_.pyd时失败。

 

观察_core_.pyd这个动态库的依赖项,主要缺失项是msvcr90.dll、msvcp90.dll(我用的vc2008编译wxPython)。拷贝这两个文件到_core_.pyd所在目录,再在gvim的命令行中键入:py import wx,仍然报错,不过这次是弹出windows消息框,说“An application has made an attempt to load the C runtime library without using a manifest”。

 

打开_core_.pyd这个文件,搜索关键字“manifest”,看到内嵌的manifest,发现仅依赖于“Microsoft.Windows.Common-Controls”,对比编译wxPython时生成的其他manifest文件知道,还少了“Microsoft.VC90.CRT”项,从我的wxPython的lib\vc_dll目录中随便拷贝一个manifest文件(如wxmsw28uh_adv_vc.dll.manifest),用mt工具嵌入_core_.pyd中即可:

mt -nologo -manifest wxmsw28uh_adv_vc.dll.manifest -outputresource:_core_.pyd;2

再一测试发现,所有的pyd文件的内嵌manifest都有问题,用上面的命令依次更新每个pyd文件即可。

 

总结一下,我在windows下用gvim编写python代码,访问wxPython库时gvim自带的自动补全失效,原因是用wxPython 2.8.12.1官方自带的编译脚本输出的*.pyd文件都被嵌入了错误的manifest,修复方法是,找一个编译wxPython时生成的完整的manifest依次嵌入所有的*.pyd文件。

 

作为参考,我所嵌入的manifest文件内容(当然和我所使用的vc版本有关):

<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level='asInvoker' uiAccess='false' />
</requestedPrivileges>
</security>
</trustInfo>
<dependency>
<dependentAssembly>
<assemblyIdentity type='win32' name='Microsoft.VC90.CRT' version='9.0.21022.8' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
</dependentAssembly>
</dependency>
<dependency>
<dependentAssembly>
<assemblyIdentity type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*' />
</dependentAssembly>
</dependency>
</assembly>

 

另外,之所以python解释器和其他python容器程序能够成功import wx,是因为他们在import wx之前已经加载好了正确版本的crt(比如python解释器本身就是vc2008编译的) ,而gvim是c语言编写的,在import wx->import _core_的时候才第一次加载c++库,此时残缺的内嵌manifest会导致错误。

 

虽然是wxPython的bug,但还是得说微软2。

posted @ 2012-02-26 17:54  Scan.  阅读(1411)  评论(0编辑  收藏  举报