调用约定和语言绑定(bind)

标签 c api calling-convention

我对如何最好地处理公共(public) API 中的调用约定差异并使其与其绑定(bind)保持同步感到有点困惑。假设我正在编写一个 C API,通过共享对象库或 DLL 提供。现在假设我被告知我不应该在 Windows 上使用默认调用约定——也就是说,在 Linux 和其他 Unix 上我应该使用编译器使用的标准调用约定(可能是 cdecl)但是在Windows 我应该强制使用 stdcall。所以我在 header 中有一些 #ifdef 逻辑,可以根据需要设置正确的调用约定。库的 C header 必须处理这一点,因此 C 公共(public) API 可用。

现在假设我想用另一种语言为我的库编写绑定(bind)。这意味着我也必须用该语言重写调用约定逻辑(取决于当前系统),以便绑定(bind)正确映射到库。依此类推所有绑定(bind)。某些语言可能对此没有很好的(或任何)支持。

有没有更优雅的方法来做到这一点?我是否应该在任何地方都使用默认调用约定,并假设其他语言会为外部/导入函数选择正确的调用约定?我什至需要担心这些东西吗(我想是的)?谢谢。

最佳答案

许多语言使用内置或第三方库来简化对共享库的调用。这些库通常包括对这两种调用约定的支持。这方面的一个例子是 JNA用于从 java 调用 native 共享库。话虽这么说,如果您不想依赖使用单一调用约定的其他语言,您可以实现包含两种类型函数的共享库,并具有为每种类型返回适当绑定(bind)的初始化程序。例如,如果您的库有 2 个名为 function1function2 的函数,您可以这样实现它:

typedef struct
{
    int (*function1)(int a, int b);
    char* (*function2)(void);
}API;

//stdcall implementation
//these functions compiled to use stdcalling convention
int stdcall_function1(int a, int b)
{
    /*...*/
}

char* stdcall_function2(void)
{
    /*...*/
}

API getSTDCallInstance()
{
    API api;
    api.function1 = &stdcall_function1;
    api.function2 = &stdcall_function2;
    return api;
}

//cdecl implementation
//these functions compiled to use cdecl convention

int cdecl_function1(int a, int b)
{
    /*...*/
}

char* cdecl_function2()
{
    /*...*/
}

API getCDECLInstance()
{
    API api;
    api.function1 = &cdecl_function1;
    api.function2 = &cdecl_function2;
    return api;
}

如果您以这种方式实现您的库,则加载语言可以使用适当的初始化器来获取包含它们正确实现的结构的句柄。

关于调用约定和语言绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20611840/

相关文章:

Python - 从其他类中的方法检索值

c++ - rdi 寄存器用于无参数函数的目的

C 套接字和 openssl (RSA)

c - 当我调用 atoi() 函数时出现程序段错误

c - 可变参数函数中的参数如何在堆栈上传递?

ios - 有没有办法通过 Apple 后端的一些 API 导出应用商店应用内支付?

php - 如何在 PHP 中集成 Assently api 进行电子签名交易

api - 交响乐 2 : How to use the ParamConverter with a PUT method to get or create an entity object

c指针错误,获取当前时间

linux - 为什么 RCX 不用于将参数传递给系统调用,而是用 R10 代替?