在 Cython 中包装 C 代码时如何处理调用约定?

How to handle calling convention when wrapping C-code in Cython?

我正在尝试将 PDFium 与 Cython 和 运行 连接到这些 defines/signatures:

#if defined(COMPONENT_BUILD)

#if defined(WIN32)
#if defined(FPDF_IMPLEMENTATION)
#define FPDF_EXPORT __declspec(dllexport)
#else
#define FPDF_EXPORT __declspec(dllimport)
#endif  // defined(FPDF_IMPLEMENTATION)
#else
#if defined(FPDF_IMPLEMENTATION)
#define FPDF_EXPORT __attribute__((visibility("default")))
#else
#define FPDF_EXPORT
#endif  // defined(FPDF_IMPLEMENTATION)
#endif  // defined(WIN32)
#else
#define FPDF_EXPORT
#endif  // defined(COMPONENT_BUILD)

#if defined(WIN32) && defined(FPDFSDK_EXPORTS)
#define FPDF_CALLCONV __stdcall
#else
#define FPDF_CALLCONV
#endif


FPDF_EXPORT void FPDF_CALLCONV
FPDF_InitLibraryWithConfig(const FPDF_LIBRARY_CONFIG* config);

我只是习惯了简单的函数声明

return_type function_name();

如何在 Cython 中包装包含调用约定的签名?

FPDF_EXPORT 和 FPDF_CALLCONV 是宏,它们在文件中定义: https://pdfium.googlesource.com/pdfium/+/master/public/fpdfview.h

这里需要它们,因为库可用于不同的系统,并且不同的系统有不同的创建库界面的约定。

这些调用是对您熟悉的格式的扩展:

return_type function_name(args) 

例如,除非您正在为 windows 构建库,否则您会看到 FPDF_CALLCONV 消失了。

很遗憾,我找不到具体的宏或您在此处引用的函数:https://github.com/PDFium/PDFium

您可能应该添加您正在使用的库的特定版本。

但是,C 函数声明中除了 return 类型、函数名和参数外,还有其他来自 C 本身的内容。

一个不属于 C 标准的特定标准是 calling convention,它指定了发送参数和 returning 从函数如何工作。

由于指定此约定的关键字是特定于编译器的,因此将它们放在条件宏中以使代码可移植是有意义的。

也可能是为了支持不同硬件的交叉编译。

所以 FPDF_CALLCONV 很可能是这样的:

#ifdef SOME_CONDITION_TO_USE_STD_CALL
    #define FPDF_CALLCONV __stdcall
#endif

C(和 C++)程序中的另一个非标准选项是 export a function when building a DLL on Windows 的指令。

由于这是特定于平台的,要使 C 代码跨平台,它也需要在条件宏中。

所以,FPDF_EXPORT 可能是这样的:

#ifdef WINDOWS
    #define FPDF_EXPORT __declspec(dllexport)
#else
    #define FPDF_EXPORT
#endif

请注意,在其他平台上不存在这种“标记”,因此宏可以展开为空,以更熟悉的形式保留函数声明。

它也应该在你包含的 h 文件版本中留空以使用库,而不是用于编译库的版本,因为你不需要这个前缀来调用函数。

总而言之,假设您使用的库与您的平台兼容,您很可能可以在 Cuthon 界面中省略这两个宏。