Search code examples
c++cvisual-c++extern-c

How to call C++ function from C?


I know this.

Calling C function from C++:

If my application was in C++ and I had to call functions from a library written in C. Then I would have used

//main.cpp

extern "C" void C_library_function(int x, int y);//prototype
C_library_function(2,4);// directly using it.

This wouldn't mangle the name C_library_function and linker would find the same name in its input *.lib files and problem is solved.

Calling C++ function from C???

But here I'm extending a large application which is written in C and I need to use a library which is written in C++. Name mangling of C++ is causing trouble here. Linker is complaining about the unresolved symbols. Well I cannot use C++ compiler over my C project because thats breaking lot of other stuff. What is the way out?

By the way I'm using MSVC


Solution

  • You need to create a C API for exposing the functionality of your C++ code. Basically, you will need to write C++ code that is declared extern "C" and that has a pure C API (not using classes, for example) that wraps the C++ library. Then you use the pure C wrapper library that you've created.

    Your C API can optionally follow an object-oriented style, even though C is not object-oriented. Ex:

    // *.h file
    // ...
    #ifdef __cplusplus
    #define EXTERNC extern "C"
    #else
    #define EXTERNC
    #endif
    
    typedef void* mylibrary_mytype_t;
    
    EXTERNC mylibrary_mytype_t mylibrary_mytype_init();
    EXTERNC void mylibrary_mytype_destroy(mylibrary_mytype_t mytype);
    EXTERNC void mylibrary_mytype_doit(mylibrary_mytype_t self, int param);
    
    #undef EXTERNC
    // ...
    
    // *.cpp file
    mylibrary_mytype_t mylibrary_mytype_init() {
      return new MyType;
    }
    
    void mylibrary_mytype_destroy(mylibrary_mytype_t untyped_ptr) {
       MyType* typed_ptr = static_cast<MyType*>(untyped_ptr);
       delete typed_ptr;
    }
    
    void mylibrary_mytype_doit(mylibrary_mytype_t untyped_self, int param) {
       MyType* typed_self = static_cast<MyType*>(untyped_self);
       typed_self->doIt(param);
    }