0

DirectX のチュートリアルを行おうとしていましたが、C++ ではなく C でアプリケーションを書きたかったのです。そのため、C でコードを書きましたが、コンパイルしようとすると、「setupD3D」関数で多くのエラーが発生しました。そのため、ファイルの名前を .cpp に変更しました。しかし、新しいコードもコンパイルされませんでした。C と C++ を組み合わせることが問題であるか、相互参照が多すぎると思います。このコードの何が問題なのか誰か教えてもらえますか?

direct3d.h:

#include "main.h"

#ifndef DIRECT3D

#define DIRECT3D

int m_videoCardMemory;
char m_videoCardDescription[128];
ID3D11DeviceContext* m_deviceContext = 0;
D3DXMATRIX m_projectionMatrix;
D3DXMATRIX m_worldMatrix;
D3DXMATRIX m_orthoMatrix;

int setupD3D(BYTE vsync, HWND hwnd, float screenDepth, float screenNear);
void terminateD3D();
void beginScene(float red, float green, float blue, float alpha);
void endScene();

#endif

direct3d.cpp

#include "direct3d.h"
// code

main.h:

#ifndef MAIN_FUNC

#define MAIN_FUNC

#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "d3dx11.lib")
#pragma comment(lib, "d3dx10.lib")

#include <Windows.h>
#include <dxgi.h>
#include <d3dcommon.h>
#include <d3d11.h>
#include <d3dx10math.h>
#include "direct3d.h"

int breedte, hoogte;
LRESULT CALLBACK Actie(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
void main_loop(MSG* msg);
void keyevent();

#endif

main.c

#include "main.h"
// code

winstart.c

#include "main.h"
// code

エラー:

Error   86  error LNK2005: _m_deviceContext already defined in main.obj
Error   87  error LNK2019: unresolved external symbol _setupD3D referenced in function _Actie@16
Error   88  error LNK2019: unresolved external symbol _terminateD3D referenced in function _Actie@16
Error   89  error LNK2019: unresolved external symbol _beginScene referenced in function _render
Error   90  error LNK2019: unresolved external symbol _endScene referenced in function _render
Error   91  error LNK1120: 4 unresolved externals   

また、マクロの再定義に関する 84 個の警告があります。

4

3 に答える 3

5

.cpp ファイルで関数を宣言すると、コンパイラはそれを C++ コードとしてコンパイルします (純粋な C であるかどうかに関係なく)。残念ながら、C++ にはName manglingと呼ばれるメカニズムがあり、C では機能をオーバーロードできません。.c ファイル (コンパイラによって純粋な C として認識される) からそのような関数を呼び出したい場合、コンパイラはシンボル (この場合は関数) の別の名前の参照を、存在するものとは別に作成し、リンカはありません。それらをもう一致させることができます。

これを解決するには、extern "C"C から呼び出し可能にしたいすべての関数の前に を置きます。C は認識しないextern "C"ため、この言語に依存させる必要があります。

この問題を解決する一般的な方法は、ヘッダー ファイルに次の構造を導入することです。

... your include guard of choice

#ifdef __cplusplus
    extern "C" {
#endif

//-- your declarations

#ifdef __cplusplus
    }
#endif

これは、C++ コンパイラに C 準拠の名前を作成するように指示します。C コンパイラはプリプロセッサ シンボル「__cplusplus」を提供しないため、extern ステートメントは無視されます。(Cコンパイラは常にC準拠のシンボル名のみを作成するため、これは問題ありません)

ヘッダー ファイルを変更する代わりに (許可されていない場合もあります)、以下に含まれるヘッダー ファイル全体をインクルードすることもできますextern "C"

extern "C" {
    #include <My_C_API.h>
}
于 2013-01-30T14:37:06.870 に答える
1

リンク エラーには次の 2 種類があります。

Error   86  error LNK2005: _m_deviceContext already defined in main.obj

これは、ヘッダー ファイルで定義m_deviceContextしてから、そのヘッダー ファイルを複数のコンパイル ユニット (少なくとも direct3d.cpp、main.c、および winstart.c) にインクルードするためです。ヘッダー ファイルから定義を移動し、インクルードの依存関係にも注意してください (main.h と direct3d.h は相互に依存しています。これは奇妙に思えます)。

Error   87  error LNK2019: unresolved external symbol _setupD3D referenced in function _Actie@16
Error   88  error LNK2019: unresolved external symbol _terminateD3D referenced in function _Actie@16
Error   89  error LNK2019: unresolved external symbol _beginScene referenced in function _render
Error   90  error LNK2019: unresolved external symbol _endScene referenced in function _render
Error   91  error LNK1120: 4 unresolved externals  

C と C++ のコードを間違って混在させているためです。すべてを C コンパイラ (または C++ コンパイラ) でコンパイルするか、extern "C". 詳細については、例を確認してください。C++ FAQ Liteの関連セクション。

于 2013-01-30T14:39:50.183 に答える
0

このエラーは、何かが main.o で既に定義されていることを示しています。あなたがすることは、ガードの前にインクルードを置くことです。そのため、そのファイルが何をインクルードしても、重複したコードが作成される可能性があります。そして、循環依存関係があります。

ファイル direct3d.h 内:

#include "main.h"
#ifndef DIRECT3D
#define DIRECT3D

そのはず:

#ifndef DIRECT3D
#define DIRECT3D
#include "main.h"

main.c のインクルード:

#include "main.h"

main.h を含む direct3d.h に既に含まれているため、これは問題です。

したがって、コンパイラはおそらく次のようになります。

#include "main.h"
#include "direct3d.h"
#include "main.h"   <-- duplicate code detected
throw error.

また、C と C++ を混在させても問題はありません。

于 2013-01-30T14:33:48.137 に答える