Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
DECLSPEC和SDLCALL在Linux头文件中的函数定义中是什么意思?_C_Linux_Sdl - Fatal编程技术网

DECLSPEC和SDLCALL在Linux头文件中的函数定义中是什么意思?

DECLSPEC和SDLCALL在Linux头文件中的函数定义中是什么意思?,c,linux,sdl,C,Linux,Sdl,我在浏览SDL2头文件时发现,我遇到的大多数函数都有以下形式: extern DECLSPEC int SDLCALL SDL_FunctionName(); 我理解extern、int和SDL_FunctionName的全部含义(分别是存储类说明符、返回值和函数名)。然而,我必须承认,我以前从未见过像DECLSPEC和SDLCALL这样的软件。搜索前者只会产生一个Win32/64API的东西,而对后者则没有什么好处 这两件事是什么意思?它们是做什么的?它们是预处理器的定义。它们用于使代码跨平

我在浏览SDL2头文件时发现,我遇到的大多数函数都有以下形式:

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)