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*)"、参照元: _main in layoutquality-I8HOqy.o ld: アーキテクチャ x86_64 のシンボルが見つかりません

ファイルvec.cload_dmat内の単なる関数です。最初の行でを に置き換えるgccg++、すべてが正常にコンパイルおよびリンクされますが、clang は次のように述べています。

clang: 警告: C++ モードでは 'c' 入力を 'c++' として扱います。この動作は非推奨です

これらをコンパイルしてリンクする、攻撃的で非推奨の方法はありますか? OS X Mavericks と新しいコマンド ライン ツールにアップグレードする前にg++、オブジェクト ファイルとのリンクは正常に機能していました。gcc何が変わったのか、どのように前進するのかについての洞察は素晴らしいでしょう、ありがとう。

4

3 に答える 3

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)

ご覧のとおり、 と を使用して、コンパイラへの 2 つの別々の呼び出しでオブジェクトを個別に生成しCXXFLAGSますCFLAGS。Xcode の clang を使用する Mac のコンテキストでは、clang ( CC) と clang++ ( CXX) は実際には同じものです。異なるフラグのみが重要です。上記の例のCCとの定義を述べることで、私は衒学的に説明しています。CXXMakefile

オブジェクト ファイルが生成されたら、それらをリンクします。

ただし、C++コードを C プログラムで使用できるようにするには、追加の手順を 1 つ実行する必要があることに注意してください。

このCPP.h例では、で使用するコードのextern "C"リンケージを明示的に指定する必要があります。C++C

たとえば、次のようにします。

#ifdef __cplusplus
extern "C" {
#endif

double timesTwo(double number);

#ifdef __cplusplus
}
#endif

プリプロセッサ マクロ#ifdef __cplusplus#endifは、ヘッダー ファイルが C モードのコンパイル エラーを引き起こさず、C++ モードのコンパイル中にのみ有効であることを確認するためのものです。

この完全な例は、4 つのファイルのみで構成されています。

  • メイクファイル
  • main.c
  • CPP.h
  • CPP.cpp

Makefileソースとは上で説明されCPP.hています。

完全に理解するために、ここにもmain.cとを含めCPP.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指定してC++ と C の相互運用を可能にし、make を実行したときに誤った clang 警告が発生しない方法が明確になると信じています。#ifdef __cplusplusextern "C"

于 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 に答える