TCC编译带通用对话框及资源的简单记事本程序
前些天一直研究lua,由此也会关注跟lua很有相似性和相关性的TCC(Tiny C Compiler)……跟Lua一样都是好东西呀~
昨天的时候,由于看到了一篇简单的示例程序《用C编写的记事本》,我突发奇想,想用TCC编译它试试……
首先,我们先回顾一下用gcc编译这个程序的过程:
windres note.rc rc.o
gcc -mwindows rc.o note.c -o note.exe -lcomdlg32 -lgdi32
先用windres编译资源成目标文件,然后把资源和C文件一起编译就行了……因为gcc默认关联kernel32和user32库,所以不用显式添加……
我这边XP机器上用MinGW编译出来的32位的程序大约有83.6KB……
下面是TCC编译的过程,编译出来的32位程序大约28KB,果然小巧的多……
直接编译的话TCC会报找不到OPENFILENAME结构的定义……
那么首先要把OPENFILENAME的定义搞进去,在gcc中就是commdlg.h文件……
把gcc中的commdlg.h拷进去之后,麻烦事就来了,因为commdlg.h中引用了另外两个文件unknwn.h和prsht.h……
这两个文件引入后就会陷入更大的引入陷阱,最后还有各种的重定义warnning出现,我们需要想个办法将其规避过去……
那么看这两个文件引入的注释:
#include <unknwn.h> /* for LPUNKNOWN */
#include <prsht.h> /* for HPROPSHEETPAGE */
一个是为了引入LPUNKNOWN,一个是为了引入HPROPSHEETPAGE,仔细看,HPROPSHEETPAGE很简单,只需要改成这一行就行:
DECLARE_HANDLE(HPROPSHEETPAGE);
可是LPUNKNOWN就麻烦了,这是一个结构体指针,而且这个结构体的一些属性还指向其他的结构体,由此牵连COM组件以及远程过程调用相关的结构体……
为了避免麻烦,我不再去纠结LPUNKNOWN到底是啥了,总之它是一个指针,如果这个指针在我的程序中不会被用到,我大可不必关心这是个啥……
于是定义它为void*将其规避过去:
typedef void* LPUNKNOWN;
之后编译能够成功,连接就出了问题……因为tcc能够默认的关联gdi32、kernel32和user32,所以我们只需要解决comdlg库就行……
这个库在tcc的lib里是不默认附带的,需要我们手动产生……这就用到了tcc自带的,通过dll库导出为lib库的工具tiny_impdef……
tiny_impdef comdlg32.dll
该命令会生成comdlg32.def,将该文件放在note.c同目录里就可以……
由于comdlg32是windows默认加载的链接库,所以在执行该命令的时候也不用写路径名……
库和头文件都准备好了,然后就可以进行编译了:
tcc note.c comdlg32.def
编译成功,但是没有链接资源,所以编译之后的exe没有图标,打开之后也没有菜单……这个记事本的功能都在菜单上,没有菜单也是基本不可用的……
关于tcc编译资源研究了一下,看tcc的帮助文档发现tcc本身不能编译rc资源,到最后还是要借助windres工具先编译成目标文件,然后tcc再一起连接……
所以,真正用tcc编译该记事本的命令是这样的:
windres note.rc rc.o
tcc note.c rc.o comdlg32.def
具体的整个目录可以在这里下载查看~最后编译出来运行的效果大约是这样的: