举这样一个例子:
使用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("%sn",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 __cplusplus11 extern "C" {12 #endif13 14 DLLIMPORT int HelloWorld (const char * pStr);15 16 #ifdef __cplusplus17 };18 #endif19 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("%sn",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"
原文链接: https://www.cnblogs.com/thmiles/archive/2011/08/04/extern-C.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/29929
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!