Linking C from C++ in OS X Mavericks

有些话、适合烂在心里 提交于 2019-11-30 03:23:09

问题


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 offending pair of commands produced from my makefile are:

gcc `pkg-config --cflags glib-2.0` -g -Wall -O3 `pkg-config --cflags flann`   -c -o vec.o vec.c
g++ `pkg-config --cflags glib-2.0` -g -Wall -O3   -stdlib=libstdc++ -lstdc++  layoutquality.cpp vec.o  `pkg-config --libs glib-2.0`  -L/usr/local/Cellar/flann/1.8.4/lib -lflann -o layoutquality

To which the linker complains:

Undefined symbols for architecture x86_64: "load_dmat(char const*)", referenced from: _main in layoutquality-I8HOqy.o ld: symbol(s) not found for architecture x86_64

Where load_dmat is just a function in the file vec.c . If I replace the gcc with g++ in the first line, then everything compiles and links fine, but clang says:

clang: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated

Is there an inoffensive, non-deprecated way of compiling and linking these? Linking with g++ together with object files from gcc worked fine before I upgraded to OS X Mavericks and the new command line tools. Any insight into what changed and how to go forward would be great, thanks.


回答1:


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



回答2:


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.

  • Makefile
  • main.c
  • CPP.h
  • CPP.cpp

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.




回答3:


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


来源:https://stackoverflow.com/questions/19644816/linking-c-from-c-in-os-x-mavericks

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!