在共享库中使用 fastcall 安全吗?

发布于 2024-08-06 03:49:45 字数 433 浏览 5 评论 0原文

例如,假设我有一个函数可以为您交换 32 位值中的字节:将

uint32_t byte_swap(uint32_t in);

32 位值压入堆栈并再次将其弹出似乎很愚蠢,特别是如果我们要调用这个函数很多,所以让我们通过 ECX 传递它:

#if __FASTCALL_SUPPORTED_   /* Whatever this may be */
#define FASTCALL __attribute__((fastcall))
#else
#define FASTCALL
#endif

uint32_t FASTCALL byte_swap(uint32_t in);

现在我的问题是,将该函数编译到共享库中进行分发是否安全?如果用户使用不同的编译器来编译他们的程序并链接到此,该函数是否仍然可以正确调用?

For example, let's say I have a function that will swap bytes in a 32 bit value for you:

uint32_t byte_swap(uint32_t in);

Well it seems silly to push that 32-bit value onto the stack and pop it off again, especially if we're going to be calling this function a lot, so let's pass it in through ECX:

#if __FASTCALL_SUPPORTED_   /* Whatever this may be */
#define FASTCALL __attribute__((fastcall))
#else
#define FASTCALL
#endif

uint32_t FASTCALL byte_swap(uint32_t in);

Now my question is, is it safe to compile that function into a shared library for distribution? If the user uses a different compiler to compile their program and links against this, will the function still be called properly?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

谎言 2024-08-13 03:49:45

__attribute__((fastcall)) 是一个 gcc 扩展;因此,如果调用者也没有使用 gcc,它可能无法使用。此外,在您提供的示例中,如果未定义 __FASTCALL_SUPPORTED_ ,您最终会得到一个具有错误调用约定的调用 - 想法。

解决这个问题的一种方法可能是使用后备包装器。在您的 .c 文件中:

#include "foo.h"

uint32_t FASTCALL byte_swap(uint32_t in) {
    /* code ... */
}

uint32_t byte_swap__slowcall(uint32_t in) {
    return byte_swap(in);
}

在您的 .h 文件中:

#if __FASTCALL_SUPPORTED_   /* Whatever this may be */
#define FASTCALL __attribute__((fastcall))
#else
#define FASTCALL
#define byte_swap byte_swap__slowcall
#endif

uint32_t FASTCALL byte_swap(uint32_t in);

另外,请注意,在 Linux 上, 中提供了快速字节交换实现,如 bswap_32。在 x86 机器上,它将编译为内联汇编程序,以及足够高的 -march= 设置上的单个指令。

__attribute__((fastcall)) is a gcc extension; as such, it may not be usable if the caller is not using gcc as well. Moreover, in the sample you gave, if __FASTCALL_SUPPORTED_ is not defined, you'll end up with a call with the wrong calling convention - bad idea.

One way to deal with this may be using a fallback wrapper. In your .c file:

#include "foo.h"

uint32_t FASTCALL byte_swap(uint32_t in) {
    /* code ... */
}

uint32_t byte_swap__slowcall(uint32_t in) {
    return byte_swap(in);
}

And in your .h file:

#if __FASTCALL_SUPPORTED_   /* Whatever this may be */
#define FASTCALL __attribute__((fastcall))
#else
#define FASTCALL
#define byte_swap byte_swap__slowcall
#endif

uint32_t FASTCALL byte_swap(uint32_t in);

Also, note that on Linux, a fast byteswap implementation is available in <byteswap.h> as bswap_32. On x86 machines, it will compile down to inline assembler, and a single instruction on high enough -march= settings.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文