详解VC中链接2001和链接2009的一下错误解决方法

  介绍

详解VC中链接2001和链接2009的一下错误解决方法?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

首先,关于VC中的自由,与linux下的静态库是不同的,在VC中编译动态库的时候会生成一个自由和一个对应的dll,使用者在使用的时候需要包含头文件以及连接到该自由,在发布最终程序的时候则需要将对应的dll拷贝到发布目录。当然也可以使用LoadLibrary的方式在程序中动态加载dll而不需要使用这个动态库生成的自由了。

如果是静态库,编译之后只会生成一个自由文件,该自由文件非常大,可能有几十米的大小,(而编译动态库的时候生成的自由可能只有几十KB或者几百KB)在使用这个静态库的自由的时候,也需要指定头文件,与对应的lib库文件,编译成功之后就可以直接运行,不需要拷贝额外的文件了。

另外如果一个是静态库,B是静态库,并且B使用了一个的接口,这个时候在编译B的时候只需要指定一个的头文件就可以了,不需要指定一个的库文件。如果有一个项目C编译成可执行文件,C使用了B中的接口,这个时候在编译C的时候,需要同时指定B的头文件(如果该头文件中又引用了一个的头文件那可能也要同时指定一个的头文件),与B的lib库文件,以及一个的lib库文件。也就是说编译C的时候要指定之前所有依赖的自由文件。

在windows中编译动态库的时候,如果动态库中的函数需要给别人使用,那么这些函数或者类则需要被导出,具体如下,假设库的头文件为A。h:

#如果定义LIB_A//这个宏为这一个特有的宏   #定义DLLEXP使用__declspec (dllexport)   其他#   #定义DLLEXP __declspec (dllimport)   # endif      类DLLEXP ExportClass {//?   };

如果在项目B中使用库,那么项目B在引用。B h的时候,由于项目没有定义LIB_A这个宏,所以实际上使用的是# define DLLEXP __declspec (dllimport)这个定义,也就是说在B项目中,这个ExportClass类的声明变成导入了,表示该类是从外部库导入的类。而在项目一个中由于定义了LIB_A这个项目特有的宏,所以使用的是# define DLLEXP使用__declspec (dllexport)这个定义,说明需要编译成导出给别人用的类。

如果是C语言的库给c++使用或者c++的库封装给C使用则除了要添加使用__declspec (dllexport)导出声明之外,还需要添加外部“C"的声明,该声明主要告诉编译器,编译的时候生成的函数的符号表按照C的规则来生成。因为C编译器与c++编译器生成符号表的时候规则是不一样的。

那么编译的时候报告链接错误,无法解析的外部符号,一般是下面几种原因造成的:

1。最常见的情况是要么没有指定引用库的路径,或者没有指定所以依赖的库文件名字。
2。如果正确指定了lib库路径,以及自由库名,那检查一下该自由中是否有该符号的实现,也就是说头文件中声明了该符号,但是该库文件中却没有具体的实现。
3。如果库文件中确实实现了符号的定义,那么检查一下lib库的版本是否与正确(32位或64位)者。还有如果报告的是某一个函数无法解析,则要对比一下该函数在库中的实现与在头文件中的声明是否一致(特别是函数的参数个数与参数类型是否完全一致)。
4。有一种情况就是在编译自由的时候,该自由是动态库,但是没有添加导出声明,导致该库中的函数并不对外导出(静态库不需要导出声明,加了反而会有问题),那么使用者在链接的时候也会报无法解析的符号。
5。还有一种非常隐蔽的情况,这也是我遇到的情况,在项目一个中将一些基本的数据类型做了typedef,例如类似下面的定义:

typedef unsigned char uint8_t;
类型定义无符号短整型uint16_t;

然后一项目的导出函数FUNC (uint8_t);使用了该uint8_t,但是在B项目中对上述的uint8_t又做了另外一套定义(如果A和B是两个开源项目则很有可能出现这种冲突),如下:

类型定义无符号__int8 uint8_t;

那么在B中使用一个的时候,使用的uint8_t是B的定义,实际上函数的声明变成了FUNC(无符号__int8)但是在一个的lib库文件的实现里面使用的是FUNC (unsigned char)也就是说该函数函数的声明与定义并不匹配,那么当然也会报告找不到符号了,这种情况一般是在两个开源项目混合使用的时候就会出现冲突。

6。编译静态库的时候,如果静态库B引用了静态库一个中的内容,此时在B的项目里面都不需要指定一个的库路径,只需要指定一个的相关头文件,就可以编译通过,如果里面有什么问题,那么会在最终使用B的项目的时候,链接的时候报出来,例如C项目使用了B,那么在编译C的时候需要同时添加A和B两个库,如果之前B使用一个的过程中有问题的话,那么在编译C的时候就会报告链接错误,而不是在编译B的时候报告(除非是语法错误)。

详解VC中链接2001和链接2009的一下错误解决方法