Search code examples
c++visual-studiolinker-errorsdllexport

Error LNK2028 when calling exported C function from C++ wrapper


I have C project from which I export function f() and call it from other C++ project and it works fine. However, when I call some other function g() inside f I get LNK2028 error.

The minimal example of Cproject looks like:

Test.h

#ifndef TEST_H
#define TEST_H

#include "myfunc.h"
#define EXTERN_DLL_EXPORT extern "C" __declspec(dllexport)

EXTERN_DLL_EXPORT void f()
{
    g();    // this will provide LNK2028 if f() is called from other project
}

#endif

myfunc.h

void g();

myfunc.c

#include "myfunc.h"
void g(){}

The project itself is being built. However, when I call this function from other C++/CLIproject

#include "Test.h"
public ref class CppWrapper
{
 public:
    CppWrapper(){ f(); }   // call external function        
};

I get error:

error LNK2028: unresolved token (0A00007C) "void __cdecl g(void)" (?g@@$$FYAXXZ) referenced in function "extern "C" void __cdecl f(void)" (?f@@$$J0YAXXZ)   main.obj    CppWrapper
error LNK2019: unresolved external symbol "void __cdecl g(void)" (?g@@$$FYAXXZ) referenced in function "extern "C" void __cdecl f(void)" (?f@@$$J0YAXXZ)    main.obj    CppWrapper

Additional details:

  1. I set x64 platform for whole solution
  2. In CppWrapper I include .lib file from C project

Solution

  • Test.h

    #ifndef TEST_H
    #define TEST_H
    
    #ifdef BUILDING_MY_DLL
    #define DLL_EXPORT __declspec(dllexport)
    #else
    #define DLL_EXPORT __declspec(dllimport)
    #endif
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    DLL_EXPORT void f();
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif
    

    Test.c

    #include "Test.h"
    #include "myfunc.h"
    
    void f()
    {
        g();
    }
    

    In your C project you have to add BUILDING_MY_DLL to

    Configuration Properties > C/C++ > Preprocessor > Preprocessor Definitions
    

    The only real change is that I added the toggle between __declspec(dllexport) and __declspec(dllimport). Changes required:

    • Moved f's body to Test.c because functions imported with __declspec(dllimport) cannot have a definition already.

    Other changes:

    • Do never write extern "C" without an #ifdef __cplusplus guard, or many C compilers will not compile your code.