DECLSPEC和SDLCALL在Linux头文件中的函数定义中是什么意思?
我在浏览SDL2头文件时发现,我遇到的大多数函数都有以下形式:DECLSPEC和SDLCALL在Linux头文件中的函数定义中是什么意思?,c,linux,sdl,C,Linux,Sdl,我在浏览SDL2头文件时发现,我遇到的大多数函数都有以下形式: extern DECLSPEC int SDLCALL SDL_FunctionName(); 我理解extern、int和SDL_FunctionName的全部含义(分别是存储类说明符、返回值和函数名)。然而,我必须承认,我以前从未见过像DECLSPEC和SDLCALL这样的软件。搜索前者只会产生一个Win32/64API的东西,而对后者则没有什么好处 这两件事是什么意思?它们是做什么的?它们是预处理器的定义。它们用于使代码跨平
extern DECLSPEC int SDLCALL SDL_FunctionName();
我理解extern
、int
和SDL_FunctionName
的全部含义(分别是存储类说明符、返回值和函数名)。然而,我必须承认,我以前从未见过像DECLSPEC
和SDLCALL
这样的软件。搜索前者只会产生一个Win32/64API的东西,而对后者则没有什么好处
这两件事是什么意思?它们是做什么的?它们是预处理器的定义。它们用于使代码跨平台,因为Windows上需要DLL修饰符。当库在Windows上构建为DLL时,它被定义为
\uu declspec(dllexport)
,因此函数在外部可见。当链接到Windows上DLL的应用程序使用头时,它被定义为\uu declspec(dllimport)
,因此编译器知道在外部DLL中查找它。请参阅源代码以了解它们是如何定义的
SDLCALL
SDLCALL
将要求实现此功能。这将告诉谁将参数推送到函数(调用者或被调用者),以及在函数返回时谁清除堆栈
MSDN有一些关于不同调用约定的详细信息
DECLSPEC
表示此函数可以作为导出函数的候选函数。它主要在Windows中用于从DLL导出函数。如果您查看SDL的标题,您会发现
begin\u code.h
,其中有以下代码段要定义DECLSPEC
:
/* Some compilers use a special export keyword */
#ifndef DECLSPEC
# if defined(__WIN32__) || defined(__WINRT__)
# ifdef __BORLANDC__
# ifdef BUILD_SDL
# define DECLSPEC
# else
# define DECLSPEC __declspec(dllimport)
# endif
# else
# define DECLSPEC __declspec(dllexport)
# endif
# else
# if defined(__GNUC__) && __GNUC__ >= 4
# define DECLSPEC __attribute__ ((visibility("default")))
# elif defined(__GNUC__) && __GNUC__ >= 2
# define DECLSPEC __declspec(dllexport)
# else
# define DECLSPEC
# endif
# endif
#endif
和SDLCALL
:
/* By default SDL uses the C calling convention */
#ifndef SDLCALL
#if (defined(__WIN32__) || defined(__WINRT__)) && !defined(__GNUC__)
#define SDLCALL __cdecl
#else
#define SDLCALL
#endif
#endif /* SDLCALL */
因此,对于Linux,DECLSPEC
将被定义为:
__attribute__ ((visibility("default")))
或
根据使用的GCC版本,SDLCALL和SDLCALL将被定义为nothing
在其他平台上,这些宏可能具有不同的定义,具体取决于所使用的特定平台和编译器的需要。这些是C/C++编译器为更改符号(函数)的导出行为而定义的常量
DECLSPEC
是C/C++头文件中使用的宏。它代表\uu declspec(dllexport)
或\uu declspec(dllimport)
,具体取决于您是项目库还是消费者。有关更多详细信息,请参阅
在类的声明/拥有项目中,DECLSPEC
解析为\u DECLSPEC(dllexport)
。这告诉编译器允许从DLL外部访问这些函数。它还更改了编译器的默认命名行为(称为名称修饰或名称损坏),以允许从DLL外部更轻松地访问这些符号。看
在消费项目中,DECLSPEC
解析为\u DECLSPEC(dllimport)
。这并不是严格必要的,但它的使用允许编译器为使用的符号生成更高效的代码,例如生成thunk。看
SDLCALL
将是一个常量,用于声明函数的调用约定。您可以阅读有关调用约定的更多信息,如\uu stdcall
,\uu cdecl
等
这些宏用于使程序在许多不同的体系结构和平台上可移植,只需重新定义常量即可。通常,平台上使用的编译器或SDK全局定义了这些宏。以下是关于可见性的GCC wiki页面
共享库包含可从链接应用程序访问的所有符号(函数和变量的名称)的列表。在Linux上,默认行为一直是公开(存储在共享库的列表中)所有定义的符号,不管它们是否需要。使用新的可见性功能和额外的编译器标志,此列表中仅包含所需的符号,从而使共享库更小、更快地链接
< GCC Wiki页面集中于C++,其中的增益最引人注目,但该特性也适用于C。
这是用于DECLSPEC
。在Linux上,SDLCALL除了在定义时表示函数应该使用C调用约定外,什么都不做。很有趣。你知道我在哪里可以找到SDL的呼叫约定吗?
__declspec(dllexport)