I have a C function that I would like to call from C++. I couldn't use "extern "C" void foo()
" kind of approach because the C function failed to be compiled using g++. But it compiles fine using gcc. Any ideas how to call the function from C++?

- 730,956
- 141
- 904
- 1,278

- 1,434
- 3
- 14
- 25
-
1Could you please write some example code and `g++` error messages – Matthieu Rouget May 31 '13 at 06:27
-
@MarkGarcia C and C++ are different languages. Yes, there are things in C that don't exist in C++. I'm sick of explaining this, hence why I asked [Why shouldn't I compile C code with a C++ compiler, or write C++ code to be compilable in C?](http://stackoverflow.com/questions/16247969/why-shouldnt-i-compile-c-code-with-a-c-or-write-c-code-to-be-compilable-in) – autistic May 31 '13 at 06:31
-
It may be the opposite. _failed to be compiled using gcc. But it compiles fine using g++_... because of the `extern "C"` – Matthieu Rouget May 31 '13 at 06:31
-
7If you compile it with a C++ compiler, it's C++. C code doesn't have to compile with a C++ compiler. They are different languages. Your code isn't valid C++ and therefor doesn't compile with a C++ compiler. – xaxxon May 31 '13 at 06:31
-
3@MatthieuRouget `void valid_in_C_but_not_in_CPlusPlus(size_t size) { char variable_length_array[size]; }` – autistic May 31 '13 at 06:36
-
@undefined behaviour: never thought it was valid C (now I know it is C99)... and with `g++` it compiles correctly, however, clearly states as forbidden with `-pedantic`. Good to know, thanks. – Matthieu Rouget May 31 '13 at 06:52
-
@MatthieuRouget Another one: `struct valid_in_C { struct but_not_in_CPlusPlus { int a; } b; int c; }; struct but_not_in_CPlusPlus d;` – autistic May 31 '13 at 06:54
-
2My try: `void f(void *pv) { int *pi = pv; *pi = 42; }` ^^ – gx_ May 31 '13 at 07:33
-
You don't have to compile your 'C' code with `g++`. That's what `extern "C"` means. Compile it with `gcc`. Not a real question. – user207421 May 31 '13 at 07:58
-
1This should be left open, especially as it has good answers pointing out how the C (rather than C++) compiler can be used for the C code. – Chris Stratton May 31 '13 at 16:58
4 Answers
Compile the C code like this:
gcc -c -o somecode.o somecode.c
Then the C++ code like this:
g++ -c -o othercode.o othercode.cpp
Then link them together, with the C++ linker:
g++ -o yourprogram somecode.o othercode.o
You also have to tell the C++ compiler a C header is coming when you include the declaration for the C function. So othercode.cpp
begins with:
extern "C" {
#include "somecode.h"
}
somecode.h
should contain something like:
#ifndef SOMECODE_H_
#define SOMECODE_H_
void foo();
#endif
(I used gcc in this example, but the principle is the same for any compiler. Build separately as C and C++, respectively, then link it together.)

- 24,226
- 19
- 100
- 173
-
8@Arne Good points. Some folks schmear some C++ in their C by wrapping the `extern "C"` in the header with [`#ifdef __cplusplus`](http://stackoverflow.com/questions/3789340/combining-c-and-c-how-does-ifdef-cplusplus-work). – unwind May 31 '13 at 07:34
-
-
I was receiving the following error: Error: #337: linkage specification is incompatible with previous "foo" (declared at line 1) Now its compiling okay. Can anyone explain? – FaizanHussainRabbani Aug 25 '15 at 08:13
-
-
@Prof.Falken I get it, it was due to another header file that included same declaration, I just put mine above it. – FaizanHussainRabbani Aug 25 '15 at 08:43
-
@FaizanHussainRabbani - a nice way to avoid these problems is to put an include guard in your header files: https://en.wikipedia.org/wiki/Include_guard – Prof. Falken Jul 15 '19 at 13:29
-
1haha, perfect answer.. Thank you! I was not able to figure out, that i need to use extern "C" to the header files.. w t f .. – Iskandir Jul 04 '23 at 10:15
Let me gather the bits and pieces from the other answers and comments, to give you an example with cleanly separated C and C++ code:
The C Part:
foo.h:
#ifndef FOO_H
#define FOO_H
void foo(void);
#endif
foo.c
#include "foo.h"
void foo(void)
{
/* ... */
}
Compile this with gcc -c -o foo.o foo.c
.
The C++ Part:
bar.cpp
extern "C" {
#include "foo.h" //a C header, so wrap it in extern "C"
}
void bar() {
foo();
}
Compile this with g++ -c -o bar.o bar.cpp
And then link it all together:
g++ -o myfoobar foo.o bar.o
Rationale:
The C code should be plain C code, no #ifdef
s for "maybe someday I'll call this from another language". If some C++ programmer calls your C functions, it's their problem how to do that, not yours. And if you are the C++ programmer, then the C header might not be yours and you should not change it, so the handling of unmangled function names (i.e. the extern "C"
) belongs in your C++ code.
You might, of course, write yourself a convenience C++ header that does nothing except wrapping the C header into an extern "C"
declaration.

- 1
- 1

- 24,171
- 3
- 51
- 90
I agree with Prof. Falken's answer, but after Arne Mertz's comment I want to give a complete example (the most important part is the #ifdef __cplusplus
):
somecode.h
#ifndef H_SOMECODE
#define H_SOMECODE
#ifdef __cplusplus
extern "C" {
#endif
void foo(void);
#ifdef __cplusplus
}
#endif
#endif /* H_SOMECODE */
somecode.c
#include "somecode.h"
void foo(void)
{
/* ... */
}
othercode.hpp
#ifndef HPP_OTHERCODE
#define HPP_OTHERCODE
void bar();
#endif /* HPP_OTHERCODE */
othercode.cpp
#include "othercode.hpp"
#include "somecode.h"
void bar()
{
foo(); // call C function
// ...
}
Then you follow Prof. Falken's instructions to compile and link.
This works because when compiling with gcc
, the macro __cplusplus
is not defined, so the header somecode.h
included in somecode.c
is like this after preprocessing:
void foo(void);
and when compiling with g++
, then __cplusplus
is defined, and so the header included in othercode.cpp
is now like that:
extern "C" {
void foo(void);
}
-
5thb, I don't like the `#ifdef __cplusplus` in C code. The C code is the lower level, and it should not have to bother if it might be called from C++ code some day. Imo that `#ifdef` has its use only in C++ code if you want to provide a C binding header for a library written in C++, not the other way round. – Arne Mertz May 31 '13 at 08:09
-
2@Prof.Falken of course, but it's a define meant to be able to provide "downward" compatbility of C++ code, not for C code. – Arne Mertz May 31 '13 at 08:53
This answer is inspired by a case where Arne's rationale was correct. A vendor wrote a library which once supported both C and C++; however, the latest version only supported C. The following vestigial directives left in the code were misleading:
#ifdef __cplusplus
extern "C" {
#endif
This cost me several hours trying to compile in C++. Simply calling C from C++ was much easier.
The ifdef __cplusplus convention is in violation of the single responsibility principle. A code using this convention is trying to do two things at once:
- (1) execute a function in C -- and --
- (2) execute the same function in C++
It's like trying to write in both American and British English at the same time. This is unnecessarily throwing an #ifdef __thequeensenglish spanner #elif __yankeeenglish wrench #else a useless tool which makes the code harder to read #endif into the code.
For simple code and small libraries the ifdef __cplusplus convention may work; however, for complex libraries it is best to pick one language or the other and stick with it. Supporting one of the languages will take less maintenance than trying to support both.
This is a record of the modifications I made to Arne's code to get it to compile on Ubuntu Linux.
foo.h:
#ifndef FOO_H
#define FOO_H
void foo(void);
#endif
foo.c
#include "foo.h"
#include <stdio.h>
void foo(void)
{
// modified to verify the code was called
printf("This Hello World was called in C++ and written in C\n");
}
bar.cpp
extern "C" {
#include "foo.h" //a C header, so wrap it in extern "C"
}
int main() {
foo();
return(0);
}
Makefile
# -*- MakeFile -*-
# dont forget to use tabs, not spaces for indents
# to use simple copy this file in the same directory and type 'make'
myfoobar: bar.o foo.o
g++ -o myfoobar foo.o bar.o
bar.o: bar.cpp
g++ -c -o bar.o bar.cpp
foo.o: foo.c
gcc -c -o foo.o foo.c

- 521
- 9
- 20