Having transitioned to OS X Mavericks and XCode 5.0.1, I can no longer gracefully link compiled C files (output from gcc) to a C++ project (output from g++).
The off
Adding a "-x c" (without quotes) before "vec.c" should fix it.
If you compile multiple .c/.cpp files in the same line you can use "-x c" or "-x c++" before each list of C or C++ filenames to switch context appropriately. For example:
g++ -x c alpha.c beta.c -x c++ gamma.cpp
Here's an example Makefile
that let us use C++
code/function in a C
program.
CC=clang
CXX=clang++
CFLAGS=-Wall -g
CXXFLAGS=-Wall -g -std=c++11 -I.
DEPS=CPP.h
OBJ=main.o CPP.o
RM=rm -f
# compile only, C source
%.o: %.c
$(CC) -c -o $@ $< $(CFLAGS)
# compile only, C++ source
%.o: %.cpp $(DEPS)
$(CXX) -c -o $@ $< $(CXXFLAGS)
# link
main: $(OBJ)
$(CXX) -o $@ $^ $(CXXFLAGS)
clean:
$(RM) $(OBJ)
As you can see, we generate our objects separately using CXXFLAGS
and CFLAGS
in two separate calls to the compiler. In the context of Mac using Xcode's clang, clang (CC
) and clang++ (CXX
) are actually the same thing. Only the differing flags matter. I am just being pedantic by stating the definitions of CC
and CXX
in the above example Makefile
.
Once the object files are generated, we are good to go to link them together.
Note however that you have to do one extra step to make your C++
code usable by the C program.
In CPP.h
in this example, you have to explicitly use extern "C"
to specify linkage for your C++
code for use by C
.
For example, like this:
#ifdef __cplusplus
extern "C" {
#endif
double timesTwo(double number);
#ifdef __cplusplus
}
#endif
The preprocessor macros #ifdef __cplusplus
and #endif
are to make sure that our header file won't cause C-mode compilation errors and is only in-effect during C++-mode compilation.
This complete example comprises only 4 files.
The Makefile
source and CPP.h
are explained above.
For a complete understanding, I am including main.c
and CPP.cpp
here as well.
main.c
:
#include <stdio.h>
#include "CPP.h"
int main()
{
printf("Running main.c\n");
double ans = timesTwo(3.0);
printf("The answer from our C++ timesTwo function, when given 3.0, is %f\n", ans);
return 0;
}
CPP.cpp
:
#include "CPP.h"
double timesTwo(double number)
{
return 2 * number;
}
I trust that this explanation and example clarifies how we can set up our Makefile
, specify the #ifdef __cplusplus
preprocessor macro and extern "C"
linkage declaration to allow C++-to-C interop, and with no erroneous clang warning when we run make.
Most probably you are a victim of Name mangling. To avoid name mangling in C++, use extern "C"
around declarations, like:
#ifdef __cplusplus
extern "C" {
#endif
void load_dmat(char const*);
#ifdef __cplusplus
}
#endif