背景:与工作有关的,具体的细节就不说了(这跟某些人说“由于工作性质,我的单位名称不方便透露”等是一样的)。大意是写一个基于socket的程序,可运行于Windows,也要运行于Linux,所谓的“跨平台”。使用C++,但只使用到其中的deque、string及fstream这些东西,其它的还是停留在C层面。
在Linux写代码比较爽,一个头文件,一个CPP文件,加一个Makefile,可生成可执行文件,也可生成动态库、静态库。Linux世界中,简约无处不在。习惯了Linux,一下子在Windows下打豆豆(特别是IDE及匈牙利命名),很是不适应,但领着公司的钱,必须干活。
好容易把代码写完了,但要制作动态库给别人用,问题是我不碰VS好多年了,也不懂怎么创建动态库。一开始将原来的源代码原封不动地编译生DLL,一切顺利。但使用这个DLL就出错了。提示信息:qftp-test fatal error LNK1136: invalid or corrupt file。这是别人说的方法:在项目属性中的“Linker”下的“Additional Dependencies”添加动态库的名称。但此法不通。
下面把创建动态库过程写一下。
1、
创建DLL工程,新建Win32控制台程序,输入工程名称后按“OK”,点“Application Settings”,类型选择“DLL”,在“Empty project”前打勾,按“Finish”完成。假设工程名为foo,头文件为foo.h,实现文件为foo.cpp。
2、
编写代码,此处不提。
3、
动态库相关,Windows下必须要在每个需要导出的函数前添加__declspec( dllexport )
关键字,而Linux则不用添加额外的信息。比如我的代码是使用C++封装一个类的,所有接口都在类里面,因此需要把类中的向外提供的接口函数前添加这个关键字。为了方便起见,可以定义一个宏,如下:
1 | #define DllExport __declspec( dllexport ) |
这个DllExport在Windows下就定义为__declspec( dllexport ),而在Linux下则定义为空,这样,就不用修改代码也可在不同平台下编译、使用了。实际上,我就是这么干的。
4、
使用动态库,在VS下编译后,会生成foo.dll、foo.lib这两个文件(至于Debug版本及Release版本,不在本文范围内,不提)。将这两个文件及foo.h一起复制到需要使用的工程目录。
5、
创建测试工程,在代码中添加
1 | #include "foo.h" |
即可使用dll中的函数了。按我的理解,这个.lib是编译使用的,而.dll才是运行时需要的。
这种方法必须将动态库及可执行文件放到同一目录才能正常运行,至于其它方法,山人暂时没研究,因为写动态库是我的职责,但使用动态库却不是。像以前对Linux的动态库有一点点研究,那是以前没事找事做的时候做的。
这个问题花了1.5天时间才算搞完。主要原因是概念不清楚,问人总说查书、上网搜索。不过这范围太大了,如果有个好心人,说关键的几句话,可能就能解决问题了。不过,我山人这么久的自学历程中,这种事情比较少见。过去的事,不提也罢。
俗语说,吃一堑,长一智。像以前某些事情让我记住了符号数跟无符号数的重要区别,这次也我记住了两个系统中动态库的不同创建过程。
部分参考资源:
http://msdn.microsoft.com/zh-cn/library/ms235636.aspx
木草山人 2011.08.23