将C++和 C 结合起来

Combine C++ and C

本文关键字:结合 起来 C++      更新时间:2023-10-16

我试图做一个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

直接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

主.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 条关于宏重新定义的警告。

如果你在.cpp文件中声明函数,编译器会将其编译为C++代码(无论它是否是纯 C)。不幸的是,C++有一种称为名称重整的机制,例如允许重载函数,而 C 则不允许。如果您现在想从 .c 文件(编译器将其识别为纯 C)调用此类函数,编译器正在为符号(在您的情况下为函数)的另一个命名创建引用,而不是它们存在,并且链接器无法再匹配它们。

为了解决这个问题,你可以在每个你想被 C 调用的函数前面放一个extern "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>
}

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

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++常见问题精简版的相关部分。

该错误表明已在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++ 混合在一起没有问题。