1

メイクファイルの作成に問題があります。私のメイン ファイルは .cpp ファイルです。そのファイルには、ヘッダー ファイル helper_funcs.h を参照するインクルードがあります。次に、このヘッダー ファイルはさまざまな関数を宣言し、それぞれが独自の .c ファイルで定義されます。.c ファイルを .o ファイルにコンパイルし、.o ファイルを helper_funcs ライブラリにコンパイルしてから、もちろん .cpp ファイルからそれらを参照できるようにする必要があります (これが理にかなっていることを願っています)。

「make」と入力すると、次のようになります。

g++ -Wall -O3 -o chessboard chessboard.cpp helper_funcs.a -framework OpenGL -framework GLUT ld: warning: ignoring file helper_funcs.a, file was built for unsupported file format ( 0x2E 0x2F 0x2E 0x5F 0x43 0x53 0x43 0x49 0x78 0x32 0x32 0x39 0x2E 0x68 0x00 0x00 ) which is not the architecture being linked (x86_64): helper_funcs.a

編集: helper_funcs.a の以前のビルドを削除して再コンパイルした後、上記のエラーはなくなりましたが、結果は次のようになります。

g++ -Wall -O3 -o chessboard chessboard.cpp helper_funcs.a -framework OpenGL -framework GLUT Undefined symbols for architecture x86_64: "f1(char const*)", referenced from: _main in chessboard-MB9B95.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) make: *** [chessboard] Error 1

LDFLAGS = -framework OpenGL -framework GLUT
CFLAGS = -c -g -Wall

all: chessboard

#  Generic compile rules
.c.o:
    gcc -c -O -Wall $<
.cpp.o:
    g++ -c -Wall $<

# Generic compile and link
%: %.c helper_funcs.a
    gcc -Wall -O3 -o $@ $^ $(LDFLAGS)

%: %.cpp helper_funcs.a
    g++ -Wall -O3 -o $@ $^ $(LDFLAGS)

#  Create archive
helper_funcs.a: f1.o f2.o
    ar -rcs helper_funcs.a $^

これが chessboard.cpp の始まりです:

#define GL_GLEXT_PROTOTYPES
#include "chessboard.h"
#include "helper_funcs.h"

using namespace std;

int main() 
{ 
      // ...
      f1("arg");
      return 0;
}

helper_funcs.h:

#ifndef helper_funcs
#define helper_funcs

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <math.h>

#ifdef USEGLEW
#include <GL/glew.h>
#endif
#define GL_GLEXT_PROTOTYPES
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif

void f1(const char* where);
void f2(const char* format , ...);

#endif

以下に 2 つの関数を示します (これらには明らかにわかりやすい名前が付いていますが、最初は一般的なものにしようとしていたので、混乱を避けるためにそのまま使用します)。

f1.c

#include "helper_funcs.h"

void f1(const char* where)
{
   // blah blah blah
}

f2.c

#include "helper_funcs.h"

void f2(const char* format , ...)
{
   // blah blah blah
}
4

1 に答える 1

1

C++ としてコンパイルされたコードでは、関数f1f2を宣言する必要がありますextern "C"。ヘッダー ファイルで条件を作成して、そのマーキングを提供できます。

例えば

#ifdef __cplusplus
extern "C" {
#endif

void f1(const char* where);
void f2(const char* format , ...);

#ifdef __cplusplus
}
#endif

この理由は、関数が「名前マングリング」と呼ばれるプロセスを経てリンカーが参照するシンボルに完全な型をエンコードし、コンパイル単位全体でオーバーロード解決を可能にする方法で C++ コードがコンパイルされるためです。C にはオーバーロードの概念がないため、C コンパイラはこれを行いません。したがって、C++ コードから C 関数を呼び出す場合、またはその逆の場合、関数は C スタイルのリンケージを持つように宣言する必要があります。

于 2013-10-09T01:16:27.113 に答える