error LNK2019 【unresolved external symbol】 解决方法

一般来说,造成此错误的可能性有以下几种:

1,工程中只有头文件,缺少源文件,只有声明没有定义
2,引入第三方库,工程中只有头文件,没有加载导入库(xxxx.lib)
3, 头文件,源文件中 函数声明和定义都有, 但是某个参数类型不一致
4, 调用约定不一致,C++工程引用了C风格的导入库 解决方法是用 extern "C" 包住你要引用的头文件
比如: 错误信息如下

1>testSDKDlg.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) int __cdeclTC_CreateSystem(struct HWND__ *)" (__imp_?TC_CreateSystem@@YAHPAUHWND__@@@Z) referenced in function "protected: virtual int __thiscallCtestSDKDlg::OnInitDialog(void)" (?OnInitDialog@CtestSDKDlg@@MAEHXZ)

干脆来一段英文解释:
The problem with your project is that you are using a "C" style exported library in your C++ projects. When the compiler generates mangled names for C++ functions, they are different from unmangled names generated by the C compiler and hence the C++ compiler will not be able to link with the methods imported from coredll.lib.
The solution to this problem is - while including the header windbase_edb.h, you can explicitly tell the compiler that all functions included from this header are "C" style functions by changing your inclusion as below.
extern "C"
{
#include “xxx.h”
}

再 说一下函数调用约定的几个概念:

microsoft的vc默认的是__cdecl方式,而windows API则是__stdcall如果用vc开发dll给其他语言用,则应该指定__stdcall方式

1.__cdecl
       所谓的C调用规则。按从右至左的顺序压参数入栈,由调用者把参数弹出栈。切记:对于传送参数的内存栈是由调用者来维护的。返回值在EAX中因此,对于象printf这样变参数的函数必须用这种规则。编译器在编译的时候对这种调用规则的函数生成修饰名的饿时候,仅在输出函数名前加上一个下划线前缀,格式为_functionname。 

2.__stdcall 

        按从右至左的顺序压参数入栈,由被调用者把参数弹出栈。_stdcall是Pascal程序的缺省调用方式,通常用于Win32 Api中,切记:函数自己在退出时清空堆栈返回值在EAX中。  __stdcall调用约定在输出函数名前加上一个下划线前缀,后面加上一个“@”符号和其参数的字节数,格式为_functionname@number。如函数int func(int a, double b)的修饰名是_func@12

3.__fastcall

       __fastcall调用的主要特点就是快,因为它是通过寄存器来传送参数的(实际上,它用ECX和EDX传送前两个双字(DWORD)或更小的参数,剩下的参数仍旧自右向左压栈传送,被调用的函数在返回前清理传送参数的内存栈)。__fastcall调用约定在输出函数名前加上一个“@”符号,后面也是一个“@”符号和其参数的字节数,格式为@functionname@number。这个和__stdcall很象,唯一差别就是头两个参数通过寄存器传送。注意通过寄存器传送的两个参数是从左向右的,即第一个参数进ECX,第2个进EDX,其他参数是从右向左的入stack。返回仍然通过EAX.

4.__pascal
       这种规则
从左向右传递参数,通过EAX返回,堆栈由被调用者清除

5.__thiscall

        仅仅应用于"C++"成员函数。this指针存放于CX寄存器,参数从右到左压。thiscall不是关键词,因此不能被程序员指定


猜你喜欢

转载自blog.csdn.net/machh/article/details/60869722