3

序章

私は経験豊富なプログラマーであり、オブジェクト指向パラダイムについて長年の経験があります。最近、C# や Java などの言語よりも少し低レベルの言語に慣れ、快適になろうと決心したので、Cを掘り下げて、それを使っていくつかのゲームを作成しようとしています。

すべてが順調に進んでおり、関数定義を別の .c ファイルに移動して、コードをより適切に整理しようとしています。これは、 Cに含まれるという性質のために、私が不快になり始めるところです。私はそれがどのように機能するか、またコンパイル中の前処理段階にも精通しています。問題は、これを正しく扱っているかどうかまだわからないことです。

私の問題は、ここで尋ねられたことに似ていると思います。私が知る必要があることを完全には満たしていませんでしたが。

問題

基本的に、2 つのライブラリを使用して OpenGL プロジェクトを作成しています。1 つはglew (OpenGL 関数のロード用) で、もう 1 つはGLFW (ウィンドウ処理と OpenGL コンテキスト作成用) です。2 つの .c ファイルがあり、1 つはmain.cと呼ばれ、もう1 つはwindowInitialize.cと呼ばれます。問題は、main.cwindowInitialize.cの両方が glewおよび glfw ライブラリに依存していることです。

私のmain.cファイルでは、次のインクルードを行います。

#include "includes/GLEW/glew.h"
#include "includes/GLFW/glfw3.h"
#include "windowInitialize.h"

さらに、main.cは次の関連する関数呼び出しを行います。

if (!initializeGLFW())
 return -1;

GLFWwindow *window = createOpenGLWindow(3, 3, 640, 480, "Hello OpenGL");

/* It is important that we initialize glew AFTER initializing GLFW and setting up
the OpenGL context, as GLEW needs a current context to work */
initializeGLEW();

windowInitialize.cには、関数initializeGLFWinitializeGLEW、およびcreateOpenGLWindowの定義が含まれています。ただし、main.cソースでは、メイン ループの目的で glew と glfw の両方を使用し、両方から関数などを参照してます

これで、windowInitialize.cは次のインクルードを行います。

#include "windowInitialize.h"
#include "includes/GLEW/glew.h"
#include "includes/GLFW/glfw3.h"
#include <stdio.h>

次に、関数定義の入力に進みます。それで、取引があります。glew ライブラリと glfw ライブラリ、および実際の stdio (デバッグ メッセージなどを出力するため) の場合、両方のファイルを使用する必要があります。

これは正しい方法ではないと思いますが、よくわかりません。コンパイラ/リンカーが二重宣言について文句を言わない理由は、main.c と windowInitialize.c が個別のオブジェクト コード ファイルを取得するためだと思います。

私の質問は、リンカーはこれらの宣言を実行可能ファイルに一度だけ入れるのに十分賢いですか? これらのヘッダーをいくつかの場所に含めても、ファイルサイズなどには影響しませんか? そして、これは複数のソース ファイル間で共通の依存関係を処理する正しい方法ですか? または、別のアプローチを使用する必要がありますか?

4

2 に答える 2

6

あなたが説明したことはすべて、物事を行う通常の方法のようです。2 つのコンパイル ユニットは、ライブラリからの実際の重複定義ではなく、これらのヘッダー内の関数の同じ前方宣言のみを取得しています。

私の質問は、リンカーはこれらの宣言を実行可能ファイルに一度だけ入れるのに十分賢いですか?

リンカーは確かに、インクルードするヘッダー ファイルを気にしません。これはリンカーであり、コンパイラではありません。

これらのヘッダーをいくつかの場所に含めても、ファイルサイズなどには影響しませんか?

関数の余分な/未使用の前方宣言は、バイナリ サイズに影響しません。

そして、これは複数のソース ファイル間で共通の依存関係を処理する正しい方法ですか?

はい、あなたは完全に正常な方法で物事を行っているようです。

プロジェクトでは、次のようなことを行う必要があります。

cc -c -o main.o main.c                           # compile main.c
cc -c -o windowInitialize.o windowInitialize.c   # compile windowInitialize.c
cc -o myProgram main.o windowInitialize.o -lglew -lglfw # link objects with necessary libraries to create executable

しかし、実際には、メイクファイルを使用する方が良いでしょう:

myProgram: main.o windowInitialize.o
    cc -o $@ $^ -lglew -lglfw

使用例:

$ make
cc    -c -o main.o main.c
cc    -c -o windowInitialize.o windowInitialize.c
cc -o myProgram main.o windowInitialize.o -lglew -lglfw
于 2013-07-31T21:53:29.033 に答える
1

リンカーは、実際に使用するライブラリの関数のみを使用し、一度だけ実行します。アプローチについては、私が読んでいる本では、すべてのライブラリ、関数宣言、定義を含むファイルを作成し、その 1 つのファイルのみを含めることをお勧めします。プロジェクトのすべてのファイルで個別に行うのではなく、 mydefinitions.h 。それが役に立てば幸い。

于 2013-07-31T22:00:39.160 に答える