TL;DR在 GCC 中,这仅适用于:ARM、AVR、MCORE、MSP430、NDS32、RL78、RX 和 SPU 端口
它在x86上不可用。
解决方法(由 Brendon 在评论中提出)。
完整答案
(此答案的其余部分假设您使用的是受支持的目标)
那是因为您使用的是 Windows 属性语法__declspec
和 GCC。
引用MSDN 参考__declspec
:
扩展的属性语法简化并标准化了Microsoft对 C 和 C++ 语言的特定扩展。
您应该改用或并行使用GCC 函数属性语法。
另请注意此 GCC 文章中的以下引用:
注意:Windows 和这个 GCC 功能之间的语义不同 - 例如,__declspec(dllexport) void (*foo)(void) 和 void (__declspec(dllexport) *foo)(void) 意味着完全不同的东西,而这会生成关于无法将属性应用于 GCC 上的非类型的警告。
因此,您在 GCC 中使用语法的方式也可能存在问题__declspec
(如果它甚至支持的话)。
您还应该注意,__declspec
GCC 声明它支持的唯一属性是__declspec(dllexport)
(如已经提到的GCC 属性语法链接中所述)。
因此,让我们为您的问题寻找一个通用的解决方案,但首先我们需要阅读实际的GCC 属性语法并找到以下内容:
在使用单个说明符和限定符列表的多个标识符的声明中,属性说明符列表可以紧邻声明符(第一个除外)出现在以逗号分隔的声明符列表中。此类属性说明符仅适用于它们出现在其声明符之前的标识符。例如,在
__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
}
编辑:
请务必注意,此属性是特定于平台的。我引用:
裸
此属性在 ARM、AVR、MCORE、MSP430、NDS32、RL78、RX 和 SPU 端口上可用。它允许编译器构造必要的函数声明,同时允许函数体是汇编代码。指定的函数不会有编译器生成的序言/尾声序列。只有基本的 asm 语句可以安全地包含在裸函数中(请参阅基本 Asm)。虽然使用扩展 asm 或基本 asm 和 C 代码的混合似乎可以工作,但它们不能可靠地工作并且不受支持。
引用自GCC 关于函数属性的文档。
边注
可能进一步阅读clang 属性可能会有所帮助(主要与 GCC 兼容),但这些评论似乎表明希望匹配 GCC 行为。