0

I'm trying to call C code from C++. I have 3 files: pubsub.cpp, pubsublib.c & pubsublib.h. I know I have to use extern "C" in order to call a C function from C++. I've literally tried everything, but I am still getting the following LNK2019 unresolved external symbol error:

LNK2019 unresolved external symbol _thisIsATestFunction referenced in function _main

pubsublib.c

#include "pubsublib.h"
void thisIsATestFunction()
{
    // do something
}

pubsublib.h

#ifndef pubsublib_H
#define pubsublib_H
void thisIsATestFunction();
#endif

pubsub.cpp

#include <string>
#include <iostream>

#ifdef __cplusplus
extern "C"{
#endif
    #include "pubsublib.h"
#ifdef __cplusplus
}
#endif

using namespace std;

int main() {
    thisIsATestFunction();
    return 0;
}

I have also tried to just include the functions but I'm getting the same error. I'm really lost at the moment and have searched a lot... Any help would be greatly appreciated.

Peter - Reinstate Monica
  • 15,048
  • 4
  • 37
  • 62
woutkl
  • 11
  • 1
  • 5
  • Post the error. – stark Nov 20 '16 at 15:37
  • LNK2019 unresolved external symbol _thisIsATestFunction referenced in function _main – woutkl Nov 20 '16 at 15:39
  • The C++ compiler might get confused from the prototype `void thisIsATestFunction();` because that says it can take any number of parameters, and C++ typically wants to decorate the function name with parameter information to be able to resolve ambiguous calls. Please try: `void thisIsATestFunction(void);` – Paul Ogilvie Nov 20 '16 at 15:50
  • I edited your question to add the error info. In the future, everything we need to know should be in the question, not comments. – Carey Gregory Nov 20 '16 at 15:50
  • How exactly do you compile the C file? Do you use the Visual Studio IDE? Afaik the VC++ compiler compiles everything as C++, so you'll have to wrap the implementation in "extern "C" as well. – Peter - Reinstate Monica Nov 20 '16 at 15:53
  • @PaulOgilvie In C++ `void thisIsATestFunction();` means that the function takes **no** parameters. AFAIK specifying that it takes no parameters via `void` is exclusive to C. – UnholySheep Nov 20 '16 at 15:53
  • @PaulOgilvie edited, still not working – woutkl Nov 20 '16 at 15:54
  • 1
    We still need to know how you are compiling and linking both files (e.g.: the exact commands you use) – UnholySheep Nov 20 '16 at 15:57
  • @UnholySheep, the function is compiled/declared as C, so it can take ANY number of parameters. – Paul Ogilvie Nov 20 '16 at 15:57
  • @PaulOgilvie oh right, sorry - I misunderstood your comment – UnholySheep Nov 20 '16 at 15:58
  • Wout, sorry to hear that. It was worth a try. – Paul Ogilvie Nov 20 '16 at 15:58
  • I am compiling in Visual Studio c++ compiler – woutkl Nov 20 '16 at 15:58
  • @PeterA.Schneider tried to wrap it inside another extern "C" but still not working – woutkl Nov 20 '16 at 15:59
  • I take my comment back; changing the source file name to ending with .c makes VS compile in "C mode". The extern C wrapper is not needed then. You example works nicely when I try to reproduce the problem (in VS 2013 Express desktop). – Peter - Reinstate Monica Nov 20 '16 at 16:02
  • One thing I'll try is moving the function definition into the main cpp file (this time guarding it with "extern C"). My suspicion is that you somehow do not include the file in the build process. Oh, Carey may be right: If you compile on the command line (and do not compile a project or solution which contains all files but use the compiler directly) you must mention all files explicitly. – Peter - Reinstate Monica Nov 20 '16 at 16:07
  • Tell us more about your build process. The IDE allows you to specify the language (C or C++), and by default seems to infer it by file extension. But that can be overridden (in the file properties, C/C++-Advanced-Compile As). If you are using the command line compiler make sure to specify the language properly, apparently using the option /TC or /TP, respectively. Then make sure that you link the object file... – Peter - Reinstate Monica Nov 20 '16 at 16:28
  • In VS I created in the "Visual C++" folder a "Win32 console application". Then I just build it and run it. – woutkl Nov 20 '16 at 16:31
  • If you would read my answer you would know what your problem is. – Carey Gregory Nov 20 '16 at 18:55

4 Answers4

0

It works perfectly fine when you actually link with the necessary file.

When you compile pubsub.cpp you have to add pubsublib.obj to the command line. For example, this solved the problem for me using Visual Studio 2015:

cl -c pubsublib.c
cl pubsub.cpp pubsublib.obj

If you're building with the IDE, you simply need to make sure that pubsublib.c is a dependency and pubsublib.obj is specified as input to the link step.

Carey Gregory
  • 6,836
  • 2
  • 26
  • 47
  • I think he is using different projects because the visual c++ ide will automatically link all obj files together if they are from a single project. – Andreas H. Nov 21 '16 at 10:15
  • @AndreasH.I think so too which is why I told him he has to make sure that .obj file is in the link input. – Carey Gregory Nov 21 '16 at 14:40
0

You have to add a reference to the library in your application.

If you have both projects in one solution in Visual C++ 2015 you

  • right click your application project
  • select "Add..." from the drop down menu
  • select "Reference" from the menu
  • check you library in the list

If you have each project in its own solution you

  • right click you application project
  • select "Properties"
  • open "Linker" section "Input" page
  • add your .lib file to the "additional dependencies"

Your application should compile without LNK2019 after doing so.

There are also "build dependencies" to manage, but these do not affect the libraries linked to your project (only the build order).

(I am using a german edition of Visual Studio so please fix the translations if some of them are wrong)

Andreas H.
  • 1,757
  • 12
  • 24
0

Your declaration works fine, as proves the error message (_thisIsATestFunction is indeed a C-undecorated name).

Now two possibilities remain

  • the file pubsublib.c was not compiled as C, causing the compiled function to get decorated;

  • the file pubsublib.c was compiled as C, but didn't take part to the linking.

Only your solution/project(s) file can tell the truth. Can we see a screen copy of the Solution Explorer ?

-1

This linkage error is produced when "pubsublib.c" file is compiled as C++ file (in g++). Please change your project options so that all .cpp files are compiled with g++, and all .c files are compiled with gcc.

After changing settings make sure that "pubsublib.c" file is really compiled with gcc. It can be found in compilation output like following:

g++.exe -c main.cpp -o main.o
gcc.exe -c pubsublib.c -o pubsublib.o 
g++.exe main.o pubsublib.o -o Project1.exe