gcc (GCC) 4.7.2
你好
我正在创建一个共享库,将编译在linux和dll,将编译在windows使用相同的源代码。所以我正在为linux和windows创建一个可移植的库。
在我的库的头文件中是这样的,即。module.h
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _WIN32
#define LIB_INTERFACE(type) EXTERN_C __declspec(dllexport) type
#else
#define LIB_INTERFACE(type) type
#endif
LIB_INTERFACE(int) module_init();
#ifdef __cplusplus
}
#endif
在源代码中,我有以下内容,即。module.c
#include "module.h"
LIB_INTERFACE(int) module_init()
{
/* do something useful
return 0;
}
在我的测试应用程序中,将链接并使用这个module.so,我有这个:
#include "module.h"
int main(void)
{
if(module_init() != 0) {
return -1;
}
return 0;
}
1)我上面所做的是为linux和windows创建一个可移植库的正确实现吗?
2)我只是想知道,因为我已经把函数 Package 在extern "C"
中,这样这个库就可以从一个用C++编译的程序中调用。在以下情况下,我是否仍然需要此EXTERN_C
:
#define LIB_INTERFACE(type) EXTERN_C __declspec(dllexport) type
3)EXTERN_C
的用途是什么?
在此先向您致谢,
5条答案
按热度按时间roejwanj1#
这是导出Windows的DLL API并仍然支持Linux的典型方法:
在DLL源中:
您的应用程序源是正确的。
使用上述模型,在Windows上DLL将导出API,而应用程序将导入它。如果不是在Win32上,则
__declspec
装饰将被删除。由于标头将整个接口 Package 在
extern "C"
中,因此不需要在每个接口上使用EXTERN_C
宏。extern "C"
用于告诉链接器使用C
链接而不是C++
。C链接是跨编译器的标准,而C++不是,这将DLL的使用限制在使用同一编译器构建的应用程序上。不需要将返回类型集成到API宏中。
xdnvmnnf2#
extern“C”基本上意味着你告诉编译器不要破坏你的函数名。Mangling是对函数名进行“编码”以供以后执行的过程,在C和C中有很大的不同,因为C可以有不同的函数具有相同的名称(通过重载等)。
In C++ source, what is the effect of extern "C"?
这些函数一旦被编译,就可以从任何地方调用,但是在开始之前,你可能想确定你创建的是什么类型的库(静态的还是动态的)。
另外,我建议您不要像在同一个文件中那样使用DEFINES来实现可移植性,因为在以后的开发中可能会遇到维护或可读性问题。我将创建一个基本文件,定义一个完全可移植到WIN和UNIX的接口,然后创建另外两个实现该接口但用于不同平台的库。
例如,您可以拥有:AbstractInterface.h、WinInterface.h、UnixInterface.h
然后根据平台只编译你需要的那些。
vwoqyblh3#
对于Linux,不带-fvisibility=hidden的gcc将默认导出函数,静态函数除外。
使用-fvisibility=hidden时,gcc默认情况下不会导出任何函数,除了由
对于Windows,导出的函数由
当使用导出的函数时,它们必须由
你帖子里的宏
MSVC支持,但are supported by GCC targetting Windows too不使用上述__attribute__语法。
因此,交叉的linux和windows宏如下:
有关可见性的更多详细信息,请阅读http://gcc.gnu.org/wiki/Visibility
c7rzv4ha4#
由于 C++ 特有的多态性概念,C++中定义的所有函数都被篡改了。即,为了为每个被覆盖的函数创建唯一的名称,“编译器”装饰函数名称。
由于名称修改是由“编译器”处理的,并且没有规范来严格定义名称修改规则,因此每个编译器都以不同的方式修饰名称。简单地说,gcc和msvc编译器为相同的代码创建不同的函数签名。你可以在wiki文章here中阅读更多关于名称篡改的内容。
你的module.h文件只是告诉编译器使用c风格的名称修改或者根本不修改。由于此指令,由gcc编译的库可用于链接到在visual studio中编写的二进制文件。这将帮助您分发库的二进制文件,而不是源代码。
另一方面,如果不使用EXTERN_C指令,则库和链接到库的项目应使用相同的编译器进行编译。例如,对于库和链接到该库的项目,必须使用gcc进行linux编译,使用msvc进行windows编译。
9q78igpj5#
你也可以让CMake使用CMake's generate_export_header为编译器生成一个头文件,而不是自己写一个头文件(例子取自链接页面):