I am working on a C project I got from the Internet, and I'm trying to add some functions to the project that involve linear algebra. In my previous works in C++, I usually rely on Eigen for linear algebra.
Is there a way to use Eigen for a C project? If yes, what should I do to make that work? (Simply adding Eigen header files is not enough since for example the standard C++ files do not get included automatically)
Eigen is a library which heavily uses C++ features which are not present in C. As such, it cannot be directly used from a C translation unit.
However, you can wrap the parts using Eigen in a separate shared library and expose a C interface. Here is a small example how one could write such a library.
Library interface
/* foo.h */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void foo(int arg);
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
By default, C++ uses different mangling rules than C for names of exported functions. We use extern "C" to instruct the C++ compiler to use the C rules. Because the interface file will be seen by both the C++ and the C compiler, we wrap the extern declaration in #ifdefs which will only trigger for the C++ compiler.
Library implementation
/* foo.cpp */
#include "foo.h"
#include <iostream>
extern "C" {
void foo(int arg) {
std::cout << arg << std::endl;
}
} /* extern "C" */
We also need to define C linkage in the definition of the interface. Other than that, you can use any C++ features you like in the implementation (including Eigen).
C project
/* main.c */
#include "foo.h"
int main() {
foo(42);
return 0;
}
Include the interface header and use it like any other C library.
Building
$ g++ foo.cpp -shared -fPIC -o libfoo.so
$ gcc main.c -L. -lfoo -o main
Use a C++ compiler to build the shared library libfoo.so. Use a C compiler to build the main program, linking to the shared library. The exact build steps may vary for your compiler/platform.
Related
I have a C shared object (.so file) and i can only compile it using gcc because it uses C only functions like strcpy_s.
And i have a C++ code that contain some C++ only libraries.
Is that possible to compile the shared object with gcc and my code with g++ together ?
Sure, you can link your C++ program with your shared C library. Just make sure that you tell the C++ compiler that the functions in that library have C linkage by adding extern "C" { ... } around the functions in your C library's header file:
shared_c_lib.h
#ifdef __cplusplus
extern "C" {
#endif
// all your C functions declarations/prototypes
#ifdef __cplusplus
} // extern "C"
#endif
Within extern "C" { } the macro __cplusplus is still defined. When I want to include the C version of mpi.h in the header of my library which is dynamically load this will not work as mpi.h still finds __cplusplus and will still load like it was opened by C++.
#undef __cplusplus works with gcc. But I do not want to rely on this.
So how to write a C++ program that
- uses the C++ version of mpi and
- is linked against a C-library that uses the C-Version of mpi (where #include <mpi.h> appears already in the header?
Example code:
library.h:
#ifdef __cplusplus
extern "C" {
#endif
#include <mpi.h>
void library_do(MPI_Comm comm);
#ifdef __cplusplus
}
#endif
program.cpp:
#include <library.h>
#include <mpi.h>
int main() {
MPI::Init();
// do some mpi C++ calls...
library_do(MPI::COMM_WORLD);
MPI::Finalize();
}
In case somebody wants to play the example here the library.c:
#include <stdio.h>
#include "library.h"
void library_do(MPI_Comm comm)
{
int rank;
MPI_Comm_rank(comm, &rank);
printf("MPI Rank: %d", rank);
}
And to compile everything I try with
mpicc -shared library.c -o lib.so
mpicxx program.cpp -l lib.so
__cplusplus will always be defined by the compiler if the compiler is a C++ compiler. extern "C" {} only gives you C linkage so the code inside plays nice with a C compiler.
The point of using
#ifdef __cplusplus
extern "C" {
#endif
...
#ifdef __cplusplus
}
#endif
is to prevent the name mangling that C++ does. We are basically saying dont use the name mangling like a traditional C++ function call instead leave it undecorated.
This link could be useful Name mangling
It is used to make C headers compatible with C++.
The flag __cplusplus is automatically defined in C++ compiler.
Because they are different things. extern "C" {} tells the compiler how to export symbols (see here), whereas __cplusplus tells you that you can use C++ code so your library can use different code paths inbetween #ifdefs.
The compiler outputs the following:
In file included from /usr/include/c++/4.8.2/bits/stl_algobase.h:61:0,
from /usr/include/c++/4.8.2/bits/stl_tree.h:61,
from /usr/include/c++/4.8.2/map:60,
from /usr/include/openmpi-x86_64/openmpi/ompi/mpi/cxx/mpicxx.h:38,
from /usr/include/openmpi-x86_64/mpi.h:2674,
from x1.cpp:6:
/usr/include/c++/4.8.2/bits/cpp_type_traits.h:72:3: error: template with C linkage
template<typename _Iterator, typename _Container>
^
/usr/include/c++/4.8.2/bits/cpp_type_traits.h:85:3: error: template with C linkage
template<bool>
^
...
The mpi.h header detects that it's being compiled as C++ and so includes C++ specific features. However templates (among other things) don't work with C linkage (i.e. if the header is within an extern "C" block).
Move the include above extern "C":
#include <mpi.h>
#ifdef __cplusplus
extern "C" {
#endif
void library_do(MPI_Comm comm);
#ifdef __cplusplus
}
#endif
Of course it's defined. It's still a C++ compiler that compiled the code inside the extern "C" block. It doesn't stop treating the code as C++, only makes sure to use a C calling/naming convention.
If the header cannot be compiled by a C++ compiler, the only recourse is to create a C wrapper that exposes a C++ compatible API.
If you #include <mpi.h> from a C++ program, just don't put extern "C" around it. At least OpenMPI and Intel MPI do this for you in the header itself - if __cplusplus is defined.
You probably get into trouble because some MPI implementations still define the C++ interface in mpi.h that was deleted from the standard. This obviously breaks under extern "C". For instance with OpenMP you can skip this by setting OMPI_SKIP_MPICXX. Then the double extern "C" works, but I still wouldn't recommend it.
Update: In case you can't modify the library header, just #include <mpi.h> before #include <lib.h>.
That said, you should not use the C++ bindings for MPI. They were removed from the standard more than 6 years ago, after being for 3 years...
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++?
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.)
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 #ifdefs 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.
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);
}
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
I have a problem. I wrote example code and I want to build it without the error:
main.cpp(.text+0x5): undefined reference to `test()'
Library
test1.c
#include <stdlib.h>
void test()
{
puts("Działa");
}
test1.h
#ifndef TEST1_H
#define TEST1_H
extern void test();
#endif
makefile
all:
gcc -c ./src/test1.c -o ./lib/test1.o
ar rcs ./lib/libtest1.a ./lib/test1.o
Program
main.cpp
#include <test1.h>
int main()
{
test();
return 0;
}
makefile
all:
g++ -static -I../test1/include -L../test1/lib ./src/main.cpp -o ./build/MyApp -ltest1
What am I doing wrong?
You are compiling a C code function, but you are expecting to link a C++ function.
Because of 'type safe linkage', the function you provide is not the function that the C++ code calls.
Either in test1.h use:
#ifdef __cplusplus
extern "C" {
#endif
extern void test1(void);
#ifdef __cplusplus
}
#endif
Or:
Compile the function with the C++ compiler.
The C++ compiler will mangle the symbol names to provide type-safe linkage (a term which you should be able to search for via your preferred search engine).
The 'compiler' - actually the linker - is looking for a function with a C++ mangled name representing the C++ function with the signature 'void test1(void);'.
For example (but remember - different compilers deliberately mangle things differently), G++ 4.2.1 on MacOS X 10.6.2 generates a symbol '__Z5test1v' for the function; GCC generates a symbol '_test1'. Clearly, when the linker is looking for '__Z5test1v', the symbol '_test1' is not going to be used - it is not spelled the same. This is a good thing.
You can use 'nm -g' on the object file for the main program to see what it is looking for, and on the object file in the library to see what it is providing. And, given that the spellings are different, that is why the loader does not pick up the library function - it is looking for something with a different name.
You are calling a C function from a C++ function. The naming between the two is different (C++ mangles names to include parameter information).
Change the header file to look like this:
#ifdef __cplusplus
extern "C" {
#endif
extern void test();
#ifdef __cplusplus
}
#endif
This will tell the compiler that the function follows the C naming/calling convention.
Why do we need to use:
extern "C" {
#include <foo.h>
}
Specifically:
When should we use it?
What is happening at the compiler/linker level that requires us to use it?
How in terms of compilation/linking does this solve the problems which require us to use it?
C and C++ are superficially similar, but each compiles into a very different set of code. When you include a header file with a C++ compiler, the compiler is expecting C++ code. If, however, it is a C header, then the compiler expects the data contained in the header file to be compiled to a certain format—the C++ 'ABI', or 'Application Binary Interface', so the linker chokes up. This is preferable to passing C++ data to a function expecting C data.
(To get into the really nitty-gritty, C++'s ABI generally 'mangles' the names of their functions/methods, so calling printf() without flagging the prototype as a C function, the C++ will actually generate code calling _Zprintf, plus extra crap at the end.)
So: use extern "C" {...} when including a c header—it's that simple. Otherwise, you'll have a mismatch in compiled code, and the linker will choke. For most headers, however, you won't even need the extern because most system C headers will already account for the fact that they might be included by C++ code and already extern "C" their code.
extern "C" determines how symbols in the generated object file should be named. If a function is declared without extern "C", the symbol name in the object file will use C++ name mangling. Here's an example.
Given test.C like so:
void foo() { }
Compiling and listing symbols in the object file gives:
$ g++ -c test.C
$ nm test.o
0000000000000000 T _Z3foov
U __gxx_personality_v0
The foo function is actually called "_Z3foov". This string contains type information for the return type and parameters, among other things. If you instead write test.C like this:
extern "C" {
void foo() { }
}
Then compile and look at symbols:
$ g++ -c test.C
$ nm test.o
U __gxx_personality_v0
0000000000000000 T foo
You get C linkage. The name of the "foo" function in the object file is just "foo", and it doesn't have all the fancy type info that comes from name mangling.
You generally include a header within extern "C" {} if the code that goes with it was compiled with a C compiler but you're trying to call it from C++. When you do this, you're telling the compiler that all the declarations in the header will use C linkage. When you link your code, your .o files will contain references to "foo", not "_Z3fooblah", which hopefully matches whatever is in the library you're linking against.
Most modern libraries will put guards around such headers so that symbols are declared with the right linkage. e.g. in a lot of the standard headers you'll find:
#ifdef __cplusplus
extern "C" {
#endif
... declarations ...
#ifdef __cplusplus
}
#endif
This makes sure that when C++ code includes the header, the symbols in your object file match what's in the C library. You should only have to put extern "C" {} around your C header if it's old and doesn't have these guards already.
In C++, you can have different entities that share a name. For example here is a list of functions all named foo:
A::foo()
B::foo()
C::foo(int)
C::foo(std::string)
In order to differentiate between them all, the C++ compiler will create unique names for each in a process called name-mangling or decorating. C compilers do not do this. Furthermore, each C++ compiler may do this is a different way.
extern "C" tells the C++ compiler not to perform any name-mangling on the code within the braces. This allows you to call C functions from within C++.
It has to do with the way the different compilers perform name-mangling. A C++ compiler will mangle the name of a symbol exported from the header file in a completely different way than a C compiler would, so when you try to link, you would get a linker error saying there were missing symbols.
To resolve this, we tell the C++ compiler to run in "C" mode, so it performs name mangling in the same way the C compiler would. Having done so, the linker errors are fixed.
C and C++ have different rules about names of symbols. Symbols are how the linker knows that the call to function "openBankAccount" in one object file produced by the compiler is a reference to that function you called "openBankAccount" in another object file produced from a different source file by the same (or compatible) compiler. This allows you to make a program out of more than one source file, which is a relief when working on a large project.
In C the rule is very simple, symbols are all in a single name space anyway. So the integer "socks" is stored as "socks" and the function count_socks is stored as "count_socks".
Linkers were built for C and other languages like C with this simple symbol naming rule. So symbols in the linker are just simple strings.
But in C++ the language lets you have namespaces, and polymorphism and various other things that conflict with such a simple rule. All six of your polymorphic functions called "add" need to have different symbols, or the wrong one will be used by other object files. This is done by "mangling" (that's a technical term) the names of symbols.
When linking C++ code to C libraries or code, you need extern "C" anything written in C, such as header files for the C libraries, to tell your C++ compiler that these symbol names aren't to be mangled, while the rest of your C++ code of course must be mangled or it won't work.
When should we use it?
When you are linking C libaries into C++ object files
What is happening at the
compiler/linker level that requires us
to use it?
C and C++ use different schemes for symbol naming. This tells the linker to use C's scheme when linking in the given library.
How in terms of compilation/linking
does this solve the problems which
require us to use it?
Using the C naming scheme allows you to reference C-style symbols. Otherwise the linker would try C++-style symbols which wouldn't work.
You should use extern "C" anytime that you include a header defining functions residing in a file compiled by a C compiler, used in a C++ file. (Many standard C libraries may include this check in their headers to make it simpler for the developer)
For example, if you have a project with 3 files, util.c, util.h, and main.cpp and both the .c and .cpp files are compiled with the C++ compiler (g++, cc, etc) then it isn't really needed, and may even cause linker errors. If your build process uses a regular C compiler for util.c, then you will need to use extern "C" when including util.h.
What is happening is that C++ encodes the parameters of the function in its name. This is how function overloading works. All that tends to happen to a C function is the addition of an underscore ("_") to the beginning of the name. Without using extern "C" the linker will be looking for a function named DoSomething##int#float() when the function's actual name is _DoSomething() or just DoSomething().
Using extern "C" solves the above problem by telling the C++ compiler that it should look for a function that follows the C naming convention instead of the C++ one.
The C++ compiler creates symbol names differently than the C compiler. So, if you are trying to make a call to a function that resides in a C file, compiled as C code, you need to tell the C++ compiler that the symbol names that it is trying to resolve look different than it defaults to; otherwise the link step will fail.
The extern "C" {} construct instructs the compiler not to perform mangling on names declared within the braces. Normally, the C++ compiler "enhances" function names so that they encode type information about arguments and the return value; this is called the mangled name. The extern "C" construct prevents the mangling.
It is typically used when C++ code needs to call a C-language library. It may also be used when exposing a C++ function (from a DLL, for example) to C clients.
This is used to resolve name mangling issues. extern C means that the functions are in a "flat" C-style API.
Decompile a g++ generated binary to see what is going on
To understand why extern is necessary, the best thing to do is to understand what is going on in detail in the object files with an example:
main.cpp
void f() {}
void g();
extern "C" {
void ef() {}
void eg();
}
/* Prevent g and eg from being optimized away. */
void h() { g(); eg(); }
Compile with GCC 4.8 Linux ELF output:
g++ -c main.cpp
Decompile the symbol table:
readelf -s main.o
The output contains:
Num: Value Size Type Bind Vis Ndx Name
8: 0000000000000000 6 FUNC GLOBAL DEFAULT 1 _Z1fv
9: 0000000000000006 6 FUNC GLOBAL DEFAULT 1 ef
10: 000000000000000c 16 FUNC GLOBAL DEFAULT 1 _Z1hv
11: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND _Z1gv
12: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND eg
Interpretation
We see that:
ef and eg were stored in symbols with the same name as in the code
the other symbols were mangled. Let's unmangle them:
$ c++filt _Z1fv
f()
$ c++filt _Z1hv
h()
$ c++filt _Z1gv
g()
Conclusion: both of the following symbol types were not mangled:
defined
declared but undefined (Ndx = UND), to be provided at link or run time from another object file
So you will need extern "C" both when calling:
C from C++: tell g++ to expect unmangled symbols produced by gcc
C++ from C: tell g++ to generate unmangled symbols for gcc to use
Things that do not work in extern C
It becomes obvious that any C++ feature that requires name mangling will not work inside extern C:
extern "C" {
// Overloading.
// error: declaration of C function ‘void f(int)’ conflicts with
void f();
void f(int i);
// Templates.
// error: template with C linkage
template <class C> void f(C i) { }
}
Minimal runnable C from C++ example
For the sake of completeness and for the newbs out there, see also: How to use C source files in a C++ project?
Calling C from C++ is pretty easy: each C function only has one possible non-mangled symbol, so no extra work is required.
main.cpp
#include <cassert>
#include "c.h"
int main() {
assert(f() == 1);
}
c.h
#ifndef C_H
#define C_H
/* This ifdef allows the header to be used from both C and C++. */
#ifdef __cplusplus
extern "C" {
#endif
int f();
#ifdef __cplusplus
}
#endif
#endif
c.c
#include "c.h"
int f(void) { return 1; }
Run:
g++ -c -o main.o -std=c++98 main.cpp
gcc -c -o c.o -std=c89 c.c
g++ -o main.out main.o c.o
./main.out
Without extern "C" the link fails with:
main.cpp:6: undefined reference to `f()'
because g++ expects to find a mangled f, which gcc did not produce.
Example on GitHub.
Minimal runnable C++ from C example
Calling C++ from is a bit harder: we have to manually create non-mangled versions of each function we want to expose.
Here we illustrate how to expose C++ function overloads to C.
main.c
#include <assert.h>
#include "cpp.h"
int main(void) {
assert(f_int(1) == 2);
assert(f_float(1.0) == 3);
return 0;
}
cpp.h
#ifndef CPP_H
#define CPP_H
#ifdef __cplusplus
// C cannot see these overloaded prototypes, or else it would get confused.
int f(int i);
int f(float i);
extern "C" {
#endif
int f_int(int i);
int f_float(float i);
#ifdef __cplusplus
}
#endif
#endif
cpp.cpp
#include "cpp.h"
int f(int i) {
return i + 1;
}
int f(float i) {
return i + 2;
}
int f_int(int i) {
return f(i);
}
int f_float(float i) {
return f(i);
}
Run:
gcc -c -o main.o -std=c89 -Wextra main.c
g++ -c -o cpp.o -std=c++98 cpp.cpp
g++ -o main.out main.o cpp.o
./main.out
Without extern "C" it fails with:
main.c:6: undefined reference to `f_int'
main.c:7: undefined reference to `f_float'
because g++ generated mangled symbols which gcc cannot find.
Example on GitHub.
Tested in Ubuntu 18.04.