Search code examples
c++ccompatibility

Creating a portable library to run on both linux and windows


gcc (GCC) 4.7.2

Hello,

I am creating a shared library that will compile on linux and a dll that will compile on windows using the same source code. So i am creating an portable library for both linux and windows.

In my header file for the library is this i.e. module.h

#ifdef __cplusplus
extern "C" {
#endif

#ifdef _WIN32
#define LIB_INTERFACE(type) EXTERN_C __declspec(dllexport) type
#else
#define LIB_INTERFACE(type) type
#endif

LIB_INTERFACE(int) module_init();

#ifdef __cplusplus
}
#endif

In the source I have the following i.e. module.c

#include "module.h"

LIB_INTERFACE(int) module_init()
{
    /* do something useful
    return 0;
}

And in my test application that will link and use this module.so I have this:

#include "module.h"

int main(void)
{
    if(module_init() != 0) {
    return -1;
    }
    return 0;
}

1) Is what I have done above is it a correct implementation of creating a portable library for linux and windows?

2) I am just wondering as I have wrapped the functions in extern "C" so that this library can been called from a program that has been compiled in C++. Do I still need this EXTERN_C in the following:

#define LIB_INTERFACE(type) EXTERN_C __declspec(dllexport) type

3) What is the purpose of the EXTERN_C?

Many thanks in advance,


Solution

  • This is a typical way to export a DLL API for Windows and still support Linux:

    #ifdef __cplusplus
    extern "C" {
    #endif
    
    #ifdef _WIN32
    #  ifdef MODULE_API_EXPORTS
    #    define MODULE_API __declspec(dllexport)
    #  else
    #    define MODULE_API __declspec(dllimport)
    #  endif
    #else
    #  define MODULE_API
    #endif
    
    MODULE_API int module_init();
    
    #ifdef __cplusplus
    }
    #endif
    

    In the DLL source:

    #define MODULE_API_EXPORTS
    #include "module.h"
    
    MODULE_API int module_init()
    {
        /* do something useful */
        return 0;
    }
    

    Your application source is correct.

    Using the above model, on Windows the DLL will export the API while the application will import it. If not on Win32, the __declspec decoration is removed.

    Since the header wraps the entire interface in extern "C", using the EXTERN_C macro on each interface is not required. extern "C" is used to tell the linker to use C linkage instead of C++. C linkage is standard across compilers, whereas C++ is not, limiting the use of a DLL to application built with the same compiler.

    There is no need to integrate the return type into the API macro.