Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2349026
  • 博文数量: 527
  • 博客积分: 10343
  • 博客等级: 上将
  • 技术积分: 5565
  • 用 户 组: 普通用户
  • 注册时间: 2005-07-26 23:05
文章分类

全部博文(527)

文章存档

2014年(4)

2012年(13)

2011年(19)

2010年(91)

2009年(136)

2008年(142)

2007年(80)

2006年(29)

2005年(13)

我的朋友

分类: C/C++

2012-03-06 18:15:21

很早以前, 我在收集C#开发工具时发现了一个叫 SnippetCompiler的GUI工具, 它的特点是一键开启, 你直接在里面写C#代码, 然后一键运行, 观察结果, 对于开发者, 不管你用的是什么语言, 这种快速的交互式反馈是学习的最有效途径. 至少对我是这样. 这可能是为什么lisper喜欢emacs里的SLIME的最主要原因.

我喜欢C#版的 SnippetCompiler, 至今在验证一个API的实际工作时, 仍然频繁地用到它.

我更需要一个C/C++版的, 我没找到.

我弄了一个Vim插件 SnippetCompiler, 可以一键产生一个buffer, 光标彬彬有礼地闪烁, 等着你键入你急切想验证的代码片段, 然后按F5去编译+运行的源码, 结果显示在一个输出buffer中, 常用头文件, 不管是POSIX的, 还是windows的, 还是boost的, 你尽可以一次性放好在默认样板文件里, 更进一步, 还有一个预编译头文件来加速编译.  可是, 它只是在windows+gvim上使用.

我最终还是忍受不了在linux上没有这么一个东西可用, 尽管在linux上有更多加速工作的选择, 比如alias, bash function, readline所带来的种种便利, 当我需要验证简简单单的一个API是否能如期工作时, 最经常的情形仍然是:

cd ~/c

vi test.cpp

typing...

:x

gcc -o test test.cpp  && ./test

这个过程, 经常的要添加诸如 -I/usr/include/libxml2 或 -lpthread, -lxml2 之类东西. 编辑test.cpp的过程中, 还要记得include正确的头文件. 一旦有错. goto到第二步, 循环往复. 直至成功.

我知道我windows版的 SnippetCompiler要移植到linux上有困难, 它有一个C#写的辅助进程, 有mono! 是的, 在debian上拜apt-get所赐可以轻易地安装mono, 要知道这个包在redhat的默认发行版中可是没有的. 这个过程让人吃惊地简单, 在debian上借助mono它可以运行.

但我仍需要一个不依赖于.NET的方案. 我的linux开发环境是redhat, 那里没有.NET, 即使我能费劲折腾出来可执行的mono, 也不爽, 这东西看起来象是一个异邦来客.

由于我也算写过一些vim script, 比如windows版的 SnippetCompiler就是用vim script写的, 所以深知用它写一个有一定长度的插件的麻烦.

我决定尝试用python写, 既然动用了更powerful的工具, 我的目标也决定更大一点: 多线程在后台调用编译器, 程序运行的同时, 不影响当前的vim编辑操作. 运行过程可以用快捷键来撤消.

先是在debian上尝试写, 其python是2.6版的. 然后移植到redhat上, python 是2.4的, 出问题, subprocess模块的一些方法在2.4上还不存在, 好像函数参数传递的机制也有些不同, 在vim中调试实在是很麻烦. 基本上我是借助于全局变量来记录程序的运行情况和抛出异常的情况. 如果有顶层未处理的异常, 在vim中按一下空格会显示异常的栈信息, 在vim内嵌的python中, print的输出结果会送到vim的message显示区(不是status区), 一个目前对我有用的处理异常的方式是

try:

    ...

except:

    global ex_msg

    ex_msg = sys.exc_info()

 

然后在vim中

:py print ex_msg

好容易在redhat上把上述两个功能也调试通过了. 从中知道python的运行时版本可以这样来判断:

if sys.version_info >= (2, 6):

   ...

然后, 准备向windows版的进行改造, 这里碰到的困难更多, 原因主要是python库的实现在windows版表现不一致.

从 subprocess.Popen切换到 win32pipe, 从threading.start_new切换到 multiprocessing.Process, 至今都还没有找到稳定可靠的办法来重复地运行一个外部进程, 捕获其结果并显示在vim buffer中. 用 process explorer查看, 发现一次运行后, 新产生的线程停留在 MSVCRT90.dll 的 _endthread函数中, 证明这个线程没有正确地结束. 同时它会把vim的内部状态都搞错乱了, mapping都整没了.

网上关于python script in vim的资源比较少. 在里面再搞线程的更少, 这几天的经历也又一次加强了我的一个看法, 能用进程替换线程就尽量用, chrome的工作方式就大胆地采用了这一策略. 同一个进程中的线程是高度耦合的, 不管你在设计之初是不是把线程之间的共享和交互有意识弄得多少多清楚, 随后的维护中是太容易造成线程之间共享了太多不该共享的东西了.

另一个教训:

如果要在vim中运行外部命令, 对参数的处理最好全部封装在一个os所支持的脚本中, 在windows上是.bat, 在linux上是bash, 我在windows版的 SnippetCompiler实现中, 是直接把命令行和参数传递给子进程, 随后在移植时. 意识到这一过程的麻烦之处: 处理路径中的空格和不常见字符, 考虑双引号等quoting机制在哪个软件层被处理等等. 放在一个中间文件中还有一个好处, 就是方便了事后的调试.

windows版的改造仍没找到好的办法...
阅读(1911) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~