Search code examples
ccythonpdfium

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


I'm trying to interface PDFium with Cython and ran into these 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);

I'm just used to the simple function declaration with

return_type function_name();

How to wrap signatures containing calling conventions in Cython?


Solution

  • Unfortunately, I could not find the specific macros or the function you reference here: https://github.com/PDFium/PDFium

    You should probably add what specific version of your library you are using.

    However, there are things in C function declarations besides return type, function name, and parameters that come from outside C it self.

    One specific one, which is not part of the C standard, is the calling convention, which specifies how sending parameters and returning from function works.

    Since the keywords to specify this convention are compiler specific, it makes sense to put them in a conditional macro, to make the code portable.

    It may also be done to support cross-compilation for different hardware.

    So FPDF_CALLCONV is most likely something like this:

    #ifdef SOME_CONDITION_TO_USE_STD_CALL
        #define FPDF_CALLCONV __stdcall
    #endif
    

    Another non standard option in C (and C++) programs is a directive to export a function when building a DLL on Windows.

    Since this is platform specific, to make C code cross-platform, it also needs to be in a conditional macro.

    So, FPDF_EXPORT is likely something like this:

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

    Note, that on other platforms this kind of "marking" does not exist, so the macro can expand to nothing, leaving the function declaration in a more familiar form.

    It should also be left blank in the version of h file you include to use the library as opposed to the one used to compile the library, as you don't need this prefix to call the function.

    To conclude, it is likely you can omit these two macros in your Cuthon interface, assuming the library you are using is compatible with your platform.