Search code examples
c++clinkerunresolved-external

Unresolved external calling C function from C++


I have a Visual Studio solution which has to call legacy C code from C++ code and I am getting linker errors. Eg:

1>------ Build started: Project: testapp_soln, Configuration: Debug Win32 ------
1>legacy.lib(launchit.obj) : error LNK2019: unresolved external symbol "void __cdecl legacy_task(void)" (?legacy_task@@YAXXZ) referenced in function "public: virtual void __thiscall Launchit::DoIt(void)" (?DoIt@Launchit@@UAEXXZ)
1>E:\share\code\so\TestApp\testapp_soln\Debug\testapp_soln.exe : fatal error LNK1120: 1 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

I have a static lib project called legacy with a C++ class, launchit calling the C functions in legacy C code.

Here are details of the legacy project.

legacy.h:

#ifndef LEGACY_H_
#define LEGACY_H_

extern void legacy_task (void);

extern int initialise_thing();

#endif /* LEGACY_H_ */

legacy.c

#include "legacy.h"

void legacy_task (void)
{
  /* doing things */
  initialise_thing();
}

legacy_init.c

#include <stdio.h>

int initialise_thing()
{
  printf("Doing init thing here\n");
  return 0;
}

legacy C stuff called from launchit class

launchit.hpp

#ifndef LAUNCHIT_HPP_
#define LAUNCHIT_HPP_

class Launchit
{
public:
    Launchit();
    virtual ~Launchit();
    virtual void DoIt();
};

#endif // LAUNCHIT_HPP_

launchit.cpp

#include "Launchit.hpp"
#include "legacy.h"

Launchit::Launchit() 
{
}

Launchit::~Launchit()
{

}

void Launchit::DoIt()
{
    legacy_task();
}

Then I build this as a static lib. It build just fine.

I have a console application project like this:

#include "launchit.hpp"

int main() {
    Launchit li;
    li.DoIt();
}

But this gives me linker error:

legacy.lib(launchit.obj) : error LNK2019: unresolved external symbol "void __cdecl legacy_task(void)" (?legacy_task@@YAXXZ) referenced in function "public: virtual void __thiscall Launchit::DoIt(void)" (?DoIt@Launchit@@UAEXXZ)

How can I fix this linker error?


Solution

  • Notice that the link error says that the symbol ?legacy_task@@YAXXZ was not found. This is a mingled name, derived by the C++ compiler from the function name. For compatibility with C, you need to use "extern "C" in legacy.h:

    #ifdef __cplusplus
    extern "C" {
    #endif
       void legacy_task (void);
    #ifdef __cplusplus
    }
    #endif
    

    This way, the compiler does not mangle the funtion's name.

    For a detailed discussion of extern "C", see In C++ source, what is the effect of extern "C"?