0

我试图做一个 DirectX 教程,但我想用 C 而不是 C++ 编写应用程序。所以我用 C 编写了代码,但是当我尝试编译它时,“setupD3D”函数出现了很多错误。所以我只是将一个文件重命名为.cpp。但是新代码也没有编译。我认为将 C 和 C++ 结合起来是问题所在,或者有很多交叉引用。谁能告诉我这段代码有什么问题?

直接3d.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

直接3d.cpp

#include "direct3d.h"
// code

主.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

主程序

#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

您有两种类型的链接错误:

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 回答