TL;DR 在 GCC 中,这是 only available on: ARM, AVR, MCORE, MSP430, NDS32, RL78, RX and SPU ports
是NOT available on x86。
Workaround (proposed by Brendon in the comments).
完整答案
(此答案的其余部分假设您使用的是受支持的目标)
那是因为您使用的是 Windows 属性语法,__declspec 与 GCC。
引用自MSDN reference on __declspec:
扩展的属性语法简化并标准化了 Microsoft 特定 对 C 和 C++ 语言的扩展。
您应该使用GCC function attribute syntax 代替或并行使用。
还请注意this GCC article 的以下引用:
注意:Windows 和这个 GCC 之间的语义不同
功能 - 例如 __declspec(dllexport) void (*foo)(void) 和
void (__declspec(dllexport) *foo)(void) 意味着完全不同的东西
而这会产生关于无法申请的警告
GCC 上非类型的属性。
因此,您在 GCC 中使用 __declspec 语法的方式也可能存在问题(如果它甚至支持的话)。
您还应该注意,GCC 声明它支持的唯一__declspec 属性是__declspec(dllexport)(如已经提到的GCC attribute syntax link 中所述)。
因此,让我们为您的问题寻找通用解决方案,但首先我们需要阅读实际的 GCC attribute syntax 并找到以下内容:
属性说明符列表可能会出现在声明符之前
(除了第一个)在逗号分隔的声明符列表中
使用单个列表声明多个标识符
说明符和限定符。此类属性说明符仅适用于
它们出现在其声明符之前的标识符。例如,在
__attribute__((noreturn)) void d0 (void),
__attribute__((format(printf, 1, 2))) d1 (const char *, ...),
d2 (void)
noreturn 属性适用于所有声明的函数;这
format 属性仅适用于 d1。
因此,您的问题的解决方案如下:
#ifdef __GNUC__
#define ATTRIBUTE_NAKED __attribute__((naked))
#else
#define ATTRIBUTE_NAKED __declspec(naked)
#endif
ATTRIBUTE_NAKED void DXHook_D3DPERF_BeginEvent()
{
#ifdef _MSC_VER //If using visual studio..
__asm{jmp[Addr]} //Jump to: Address stored in Addr.
#else //else using gcc..
__asm("jmp *%0"
: /*No Outputs*/
: "r" (Addr)
: "%eax");
#endif
}
编辑:
需要注意的是,这个属性是platform specific。我引用:
裸体
此属性在 ARM、AVR、MCORE、MSP430、NDS32、RL78、RX 和 SPU 端口上可用。它允许编译器构造
必要的函数声明,同时允许
函数为汇编代码。指定的功能不会有
由编译器生成的序言/尾声序列。只有基本的asm
语句可以安全地包含在裸函数中(参见 Basic Asm)。
在使用扩展 asm 或基本 asm 和 C 代码的混合时,可能
似乎可以工作,但不能依赖它们可靠地工作,并且
不支持。
引自GCC documentation on function attributes。
旁注
对clang attributes 的进一步阅读可能会有所帮助(大部分与 GCC 兼容),但these comments 似乎表明希望匹配 GCC 行为。