问题场景:
需要创建一个dll程序以实现功能:
我在创建项目的时候,新建方式为Win32 Project的方式。
程序选择类型分别有:
- Windows application
- Console application
- DLL
- Static library
我最终选择的是Widows application,在编写好代码以后,进行编译程序,出现了以下错误:
1. xxx.obj : LNK2001: unresolved external symbol "__declspec(dllimport)......"
2. MSVCRT.lib(crtexew.obj) : error LNK2001: unresolved external symbol WinMain
3. error LNK1112:module machine type 'x86' conflicts with target machine type 'x64'
解决方案
1. xxx.obj : LNK2001: unresolved external symbol "__declspec(dllimport)......
-
一开始由于需要一些lib文件,导入文件夹后没有在对应的配置里面进行设置,所以在project >> VC++ Directories >> Include Directories 和Library Directory中添加了自己需要的lib所在文件夹 。
解决第一个问题。
2. MSVCRT.lib(crtexew.obj) : error LNK2001: unresolved external symbol WinMain
搜了很多以后,了解到可能是 控制台应用程序 和 windows 程序,于是尝试改了以下两个地方:
没有作用。改成console之后会报错
改成Windows之后会报错
于是把这个问题发到了部门群里,然后问了组长,参照原来的项目,这个地方应该是windows。
于是看设置成Windows的报错,MSVCRT.lib这个文件报错,我去项目依赖的lib文件夹里面看,发现缺少MSVCRT.lib文件,便将该文件从vs2010安装文件夹里面复制到项目依赖的lib文件夹里面。
出现了第三个错误。
3. error LNK1112:module machine type 'x86' conflicts with target machine type 'x64'
查了资料之后,在Linker >> Command Line >> Additional Options里面添加了x64的配置,无效,正在解决的时候,经理来看我问题解决的怎么样,他看了之后,告诉我现在创建的项目应该是是DLL程序,而不是Windows程序。于是我将Configuration Properties >> General中的targetExtension和Configuration type都设置成.dll的设置以后解决问题并成功编译。
这里写一下自己学习“创建Win32不同程序类型的区别”的笔记:
- windows应用程序
- 控制台应用程序
- DLL
- 静态库
DLL和静态库,这两种项目类型是不可以单独运行的,必须在Windows应用程序调用他们执行,是提供的库函数而已。
DLL和静态库的区别
-
静态库(.lib)
函数和数据被编译进一个二进制文件(通常扩展名为.LIB)。在使用静态库的情况下,在编译链接可执行文件时,
链接器从库中复制这些函数和数据并把它们和应用程序的其他模块组合起来创建最终的可执行文件(.EXE文件)
。当发布产品时,只需要发布这个可执行文件,并不需要发布被使用的静态库。 -
动态库(.lib文件和.dll文件)
在使用动态库的时候,编译后往往提供两个文件:一个引入库(.lib)文件(也称“导入库文件”)和一个DLL(.dll)文件。当然到了后面会告诉你如果只提供一个DLL文件,使用
显示连接
的方式也可以调用,只是稍加麻烦而已。
虽然引入库的后缀名也是“lib”,但是,动态库的引入库文件和静态库文件有着本质的区别。对一个DLL文件来说,其
引入库文件(.lib)包含该DLL导出的
函数和变量的符号名
,而.dll文件包含该DLL
实际的函数和数据
。在使用动态库的情况下,在编译链接可执行文件时,只需要链接该DLL的引入库文件,该DLL中的函数代码和数据并不可复制到可执行文件,直到可执行程序运行时,才去加载所需的DLL,将该DLL映射到进程的地址空间中,然后访问DLL中导出的函数。这时,在发布产品时,除了发布可执行文件以外,同时还需要发布该程序将要调用的动态链接库。
只有当EXE程序确实要调用这些DLL模块的情况下,系统才会将它们装载到内存空间中
。这种方式不仅减少了EXE文件的大小和对内存空间的需求,而且使这些DLL模块可以同时被多个应用程序使用。如果DLL不在内存中,系统就将其加载到内存中。当链接Windows程序以产生一个可执行文件时,你必须链接由编程环境提供的专门的 “引入库(import library)”。这些引入库包含了动态链接库名称和所有Windows函数调用的引用信息。链接程序使用该信息在.EXE文件中构造一个表,当加载程序时,Windows使用它将调用转换为Windows函数。
引入库Lib和静态库Lib的区别:
静态库本身包含了实际执行代码、符号表等等,而对于引入库而言,其实际的执行代码位于动态库中,引入库只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息。但是引入库文件的引入方式和静态库一样,要在链接路径上添加找到这些.lib的路径
。
动态库(Lib和DLL)和静态库Lib的区别:
其实上面已经提到了区别,这里再总结一下:
(1)静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,lib 中的指令都全部被
直接包含
在最终生成的 EXE 文件中了,最终的可执行文件exe会比较大。但是若使用 DLL,该 DLL 不必被包含在最终 EXE 文件中,EXE 文件执行时可以
“动态”地引用和卸载
这个与 EXE 独立的 DLL 文件。
(2)静态链接库和动态链接库的另外一个区别在于
静态链接库中不能再包含其他的动态链接库或者静态库
,而在
动态链接库中还可以再包含其他的动态或静态链接库
。静态链接库与静态链接库调用规则总体比较如下:
静态链接库运行之前就加载了,而且一直存在直到关闭程序,动态DLL实在运行时再加载,不用一直占内存,dll模块内部更改了,是要替换Dll即可,方便维护。优点明显,但是dll如果丢失或被误删,就无法运行了
参考:
https://blog.csdn.net/dxzysk/article/details/66477147