c-调用约定和语言绑定



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

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

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

许多语言使用内置或第三方库来简化对共享库的调用。这些库通常包括对这两种调用约定的支持。其中一个例子是用于从java调用本地共享库的JNA。话虽如此,如果您不想依赖于使用单一调用约定的其他语言,则可以实现包含两种类型函数的共享库,并具有为每种类型返回适当绑定的初始化器。例如,如果您的库有两个名为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;
}

如果以这种方式实现库,那么加载语言可以使用适当的初始值设定项来获取包含正确实现的结构的句柄。

最新更新