3

Using gcc, I want to call one C function, declared in a .c file, in a .cpp program. The command I'm using is:

gcc {.cpp files} -lstdc++ {.c file}

I couldn't just convert the C file to CPP, but if I include a common header one of two things naturally happens:

  1. The CPP files don't understand what a C header is
  2. The C file doesn't understand what a CPP header is.

How do I do this? Can I somehow compile the C function before and then use it?

Rob
  • 2,618
  • 2
  • 22
  • 29
  • 3
    Disclaimer: I don't know C++. Encapsulate the declaration of the C function in a `extern "C"` block to prevent the C++ compiler to name-mangle the C function.. Maybe something like `extern "C" {` `#include ` `}` – pmg Aug 29 '20 at 13:11
  • For one the .h file is usually what is used to expose the interfaces. The interfaces are effectively a list of symbols (names/signatures). C and C++ use a different mechanism to uniquely generate the symbols mainly C++ mangles the symbols, so the two cannot understand each other. As @pmg mentioned you will need to tell C++ that the method is from C so it will use the right symbol from C, and I believe you will need to extern the C++ symbol you want to use in C differently. here is a reference: https://isocpp.org/wiki/faq/mixing-c-and-cpp – Rob Aug 29 '20 at 13:19
  • The `g++` toolchain driver can compile C files, and be used to link C files to C++ code. – Eljay Aug 29 '20 at 14:11

2 Answers2

0

The reason for this is that C++ allows overloading of methods. To allow this, the compiler tags the method name to indicate the types of parameters that can be passed (so-called "name mangling").

As mentioned in the comments, you need to use extern C declarations in any C++ method calling C. To allow C to call C++, you need an extern C method in the C++ source to allow it to be called from C. Make sense?

Structure your header accordingly so that it can be included from both C and C++ sources:

#ifdef __cplusplus
    extern "C" {
#endif

... // body of header

#ifdef __cplusplus
    } // closing brace for extern "C"

#endif

For more info see: https://www.oracle.com/technical-resources/articles/it-infrastructure/mixing-c-and-cplusplus.html

and https://www.geeksforgeeks.org/extern-c-in-c/

Den-Jason
  • 2,395
  • 1
  • 22
  • 17
0

In order to resolve this, one has to understand how are C and C++ languages compiled. I will not attempt to explain it here, others have already done much better job that I can. So, I will just mention the relevant parts.

There is nothing special about C or C++ headers, #include literally just pastes the file contents (recursively).

Every translation unit (~ one .c{pp} file and all included headers) is compiled separately into an object file containing symbol tables and (almost) compiled code.

What is likely causing the issue is either C or C++ specific code in header files (neither language is a superset of the other) or C++ symbol mangling - as pointed out by @pmg. There is not much that can be done with the former. The latter can solved using extern "C"

foo.h

void foo(void);

foo.c

#include "foo.h"

#include <stdio.h>

void foo(void){
    printf("Hello from C\n");
}

Running gcc -c foo.c will create foo.o that contains the implementation for the function symbol foo.

main.cpp

extern "C"{
#include "foo.h"
}
int main(){
   foo();
}

Similarly, g++ -c main.cpp will create main.o object file.

Then, running g++ -o program.out main.o foo.o will link them together into program.out executable.

> ./program.out
Hello from C

extern "C"{} disables symbol mangling and because the included code is just pasted there, it is applied to the whole file. So, main.o function symbol table says that it seeks foo function symbol instead of _Z3foov or something similar.

Quimby
  • 17,735
  • 4
  • 35
  • 55