这篇文章主要讲解了“c语言中一个跨平台的头文件分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“c语言中一个跨平台的头文件分析”吧!
目前创新互联建站已为近1000家的企业提供了网站建设、域名、虚拟主机、成都网站托管、企业网站设计、荥阳网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。
我们平常在写代码的时候,特别是在制造轮子的时候(为别人提供库文件),会遇到各种不同的需求场景:
有些人需要在 Linux 系统下使用,有些人需要在 Windows 系统下使用; 有些人使用 C 语言开发,有些人使用 C++ 来开发; 有些人使用动态库,有些人使用静态库;
特别是在 Windows 系统中,库文件中导出的函数需要使用 _declspec(dllexport) 来声明函数,而使用者在导入的时候,需要使用 _declspec(dllimport) 来声明函数,甚是麻烦!
利用这个头文件,再加上几个编译期间传递的宏,就可以完美的处理刚才所说的各种需求。
先直接上代码,可以先试着分析一下,后面我们再逐一分析不同的使用场景。
这个头文件的主要目的,就是定义一个宏:MY_API,然后把这个宏添加在库文件中每一个需要导出的函数或者类的声明中即可。例如:
void MY_API do_work();
下面是头文件:
_Pragma("once")
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
#define MY_WIN32
#elif defined(linux) || defined(__linux) || defined(__linux__)
#define MY_LINUX
#endif
#if defined(MY_WIN32)
#ifdef MY_API_STATIC
#ifdef __cplusplus
#define MY_API extern "C"
#else
#define MY_API
#endif
#else
#ifdef MY_API_EXPORTS
#ifdef __cplusplus
#define MY_API extern "C" __declspec(dllexport)
#else
#define MY_API __declspec(dllexport)
#endif
#else
#ifdef __cplusplus
#define MY_API extern "C" __declspec(dllimport)
#else
#define MY_API __declspec(dllimport)
#endif
#endif
#endif
#elif defined(MY_LINUX)
#ifdef __cplusplus
#define MY_API extern "C"
#else
#define MY_API
#endif
#endif
假设需要写一个库文件,提供给别人使用。定义了上面这个头文件之后,其他的文件中都要 include 这个头文件。
1. 平台宏定义不同的平台预定义了相应的宏定义,例如:
Windows 平台:WIN32, _WIN32, WIN32;
Linux 平台:linux, __linux, linux;
在一个确定的平台上,这些宏不一定全部定义,很可能只有其中的某一个宏是被定义的。
为了统一性,我们在头文件的刚开始部分,把这些可能的宏统一起来,定义我们出我们自己的平台宏定义:MY_WIN32 或者是 MY_LINUX,后面需要区分不同的平台时,就用这个自己定义的平台宏。
当然,还可以继续扩充出其他平台,例如:MY_MAC, MY_ARM 等等。
如果在写库代码的时候,使用的是 C++,而使用者使用的是 C 语言,那么就需要对库函数进行 extern “C” 声明,让编译器不要对函数的名称进行改写。
编译器 g++ 预定义了宏 __cplusplus
,因此,在头文件中,就利用了这个宏,在 MY_API
中添加 extern "C" 声明。
(1) 生成静态库
在静态库中,不需要 __declspec(dllexport/dllimport)
的声明,因此只需要区分编译器即可(gcc or g++),在编译选项中定义宏 MY_API_STATIC
,即可得到最终的 MY_API
为:
gcc 编译器:#define MY_API
g++ 编译器:#define MY_API extern "C"
(2) 生成动态库
在编译选项中,定义宏 MY_API_EXPORTS
,这样最终得到的 MY_API
就会变成:
gcc 编译器:#define MY_API __declspec(dllexport)
g++ 编译器:#define MY_API extern "C" __declspec(dllexport)
在使用库的应用程序中,也需要在代码中 include 这个头文件,然后加上编译选项中定义的各种宏,来生成对应的 MY_API
宏定义。
(1) 使用静态库
需要在编译选项中定义 MY_API_STATIC
,即可得到最终的 MY_API
为:
gcc 编译器:#define MY_API
g++ 编译器:#define MY_API extern "C"
(2) 使用动态库
在编译选项中不需要任何宏定义,即可得到最终的 MY_API
为:
gcc 编译器:#define MY_API extern "C" __declspec(dllimport)
g++ 编译器:#define MY_API __declspec(dllimport)
这样就相当于声明导入库函数了。
Linux 平台下就简单多了,只需要注意编译器的问题,而没有导出和导入之分。
感谢各位的阅读,以上就是“c语言中一个跨平台的头文件分析”的内容了,经过本文的学习后,相信大家对c语言中一个跨平台的头文件分析这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是创新互联,小编将为大家推送更多相关知识点的文章,欢迎关注!