举例理解extern “C”

举这样一个例子:

使用C语言创建一个dll库供C++客户端使用

C语言dll端

dll.h


举例理解extern "C"举例理解extern "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 DLLIMPORT int HelloWorld (const char * pStr);11 12 #endif /** _DLL_H_ */

dllmain.c(注意到后缀名是.C所以函数为按照C语言编译规则导出)
举例理解extern "C"举例理解extern "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文件

举例理解extern "C"

C++客户端

dll.h


举例理解extern "C"举例理解extern "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 DLLIMPORT int HelloWorld (const char * pStr);11 12 #endif /** _DLL_H_ */

main.cpp
举例理解extern "C"举例理解extern "C"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++客户端都可以调用该库


举例理解extern "C"举例理解extern "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_ */

再举一个例子(在一个工程中CC++语言混合使用)

ctest.c
举例理解extern "C"举例理解extern "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
举例理解extern "C"举例理解extern "C"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
举例理解extern "C"举例理解extern "C"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

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月8日 上午7:18
下一篇 2023年2月8日 上午7:19

相关推荐