10

转换到 OS X Mavericks 和 XCode 5.0.1 后,我不能再优雅地将已编译的 C 文件(从 gcc 输出)链接到 C++ 项目(从 g++ 输出)。

从我的 makefile 产生的有问题的命令对是:

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

链接器抱怨的:

架构 x86_64 的未定义符号:“load_dmat(char const*)”,引用自:layoutquality-I8HOqy.o ld 中的 _main:未找到架构 x86_64 的符号

whereload_dmat只是文件 vec.c 中的一个函数。如果我在第一行替换了gccwith ,那么一切都可以编译和链接,但是 clang 说:g++

clang:警告:在 C++ 模式下将“c”输入视为“c++”,不推荐使用此行为

是否有一种无害的、不被弃用的编译和链接方式?g++在我升级到 OS X Mavericks 和新的命令行工具之前,与来自目标文件的链接gcc工作得很好。任何有关发生了什么变化以及如何前进的见解都会很棒,谢谢。

4

3 回答 3

19

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
于 2014-06-22T03:37:24.697 回答
5

这是一个Makefile让我们C++在程序中使用代码/函数的示例C

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)

如您所见,我们分别使用编译器CXXFLAGSCFLAGS两次单独调用编译器来生成我们的对象。在 Mac 使用 Xcode 的 clang 的上下文中,clang ( CC) 和 clang++ ( CXX) 实际上是一回事。只有不同的标志很重要。我只是通过在上面的例子中说明CC和的定义来迂腐。CXXMakefile

一旦生成了目标文件,我们就可以将它们链接在一起。

但是请注意,您必须做一个额外的步骤才能使您的C++代码可供 C 程序使用。

CPP.h此示例中,您必须显式使用extern "C"为您的C++代码指定链接以供C.

例如,像这样:

#ifdef __cplusplus
extern "C" {
#endif

double timesTwo(double number);

#ifdef __cplusplus
}
#endif

预处理器宏用于确保我们的头文件不会导致 C 模式编译错误,并且仅在 C++ 模式编译期间有效#ifdef __cplusplus#endif

这个完整的示例仅包含 4 个文件。

  • 生成文件
  • 主程序
  • CPP.h
  • CPP.cpp

Makefile来源和CPP.h上面解释过。

为了全面了解,我也包括main.cCPP.cpp这里。

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;
}

我相信这个解释和示例阐明了我们如何设置Makefile、指定#ifdef __cplusplus预处理器宏和extern "C"链接声明以允许 C++ 到 C 互操作,并且在运行 make 时没有错误的 clang 警告。

于 2015-04-24T03:43:23.170 回答
1

您很可能是Name mangling的受害者。为避免 C++ 中的名称重整,请使用extern "C"环绕声明,例如:

#ifdef __cplusplus 
extern "C" {
#endif
    void load_dmat(char const*);
#ifdef __cplusplus
}
#endif
于 2013-10-28T21:40:26.330 回答