举这样一个例子:
使用C语言创建一个dll库供C++客户端使用
C语言dll端
dll.h
View Code
1 #ifndef _DLL_H_
2 #define _DLL_H_
3
4 #if BUILDING_DLL
5 # define DLLIMPORT __declspec (dllexport)
6 #else
7 # define DLLIMPORT __declspec (dllimport)
8 #endif
9
10 DLLIMPORT int HelloWorld (const char * pStr);
11
12 #endif /** _DLL_H_ */
dllmain.c(注意到后缀名是.C所以函数为按照C语言编译规则导出)
View Code
1 #include "dll.h"
2 #include <Windows.h>
3 #include <stdio.h>
4
5 DLLIMPORT int HelloWorld(const char* pStr)
6
7 {
8 printf("%s\n",pStr);
9 return strlen(pStr);
10 }
11
12
13 BOOL APIENTRY DllMain (HINSTANCE hInst,
14 DWORD reason,
15 LPVOID reserved)
16 {
17 switch (reason)
18 {
19 case DLL_PROCESS_ATTACH:
20 break;
21 case DLL_PROCESS_DETACH:
22 break;
23 case DLL_THREAD_ATTACH:
24 break;
25 case DLL_THREAD_DETACH:
26 break;
27 }
28
29 return TRUE;
30
31 }
使用dumpbin -exports查看生成的dll文件
![]()
C++客户端
dll.h
View Code
1 #ifndef _DLL_H_
2 #define _DLL_H_
3
4 #if BUILDING_DLL
5 # define DLLIMPORT __declspec (dllexport)
6 #else
7 # define DLLIMPORT __declspec (dllimport)
8 #endif
9
10 DLLIMPORT int HelloWorld (const char * pStr);
11
12 #endif /** _DLL_H_ */
main.cpp
View Code
1 #include "dll.h"
2
3 #pragma comment(lib,"externC_test.lib")
4
5 int _tmain(int argc, _TCHAR* argv[])
6 {
7 HelloWorld("Hello,World");
8 return 0;
9 }
结果编译链接时:error LNK2019: 无法解析的外部符号 "__declspec(dllimport) int __cdecl HelloWorld(char const *)" (__imp_?HelloWorld@@YAHPBD@Z)
分析:
C++支持函数重载,而C不支持,两者的编译规则也不一样。函数被C++编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为: void foo( int x, int y ); 该函数被C编译器编译后在符号库中的名字可能为_foo,而C++编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字称为“mangled name”)。_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的
解决方法:
一、在C动态库端将dllmain.c的后缀名改为.cpp,使函数按照C++的编译规则导出,但不建议这样,这样一来使用C语言的客户端将不能调用该库
二、修改dll.h头文件,推荐使用该方法,这样不管是C客户端还是C++客户端 都可以调用该库
View Code
1 #ifndef _DLL_H_
2 #define _DLL_H_
3
4 #if BUILDING_DLL
5 # define DLLIMPORT __declspec (dllexport)
6 #else
7 # define DLLIMPORT __declspec (dllimport)
8 #endif
9
10 #ifdef __cplusplus
11 extern "C" {
12 #endif
13
14 DLLIMPORT int HelloWorld (const char * pStr);
15
16 #ifdef __cplusplus
17 };
18 #endif
19
20 #endif /** _DLL_H_ */
再举一个例子(在一个工程中C和C++语言混合使用)
ctest.c
View Code
1 #include <Windows.h>
2 #include <stdio.h>
3
4 int testFunc(const char* pStr)
5 {
6 printf("%s\n",pStr);
7 return strlen(pStr);
8 }
main.cpp
View Code
1 int testFunc(const char* pStr);
2
3 int main(int argc, char* argv[])
4 {
5 testFunc("hello,world");
6 return 0;
7 }
编译链接时 : error LNK2001: 无法解析的外部符号 "int __cdecl testFunc(char const *)" (?testFunc@@YAHPBD@Z)
修改main.cpp
View Code
1 extern "C" int testFunc(const char* pStr);
2
3 int main(int argc, char* argv[])
4 {
5 testFunc("hello,world");
6 return 0;
7 }
总结:
一、被extern "C"修饰的变量和函数是按照C语言方式编译和连接的
二、extern "C"的真实目的是 : 实现C++与C及其它语言的混合编程
三、注意在C语言的源文件.c中不能使用extern "C"

浙公网安备 33010602011771号