DirectX 9 CreateDevice 在 C 中失败,但在 C++ 中成功

DirectX9 CreateDevice fails in C, but succeds in C++

我在 C 中制作了一个 d3d9 应用程序,但是当尝试创建一个设备对象时,它在 C 中失败了,但是它在 C++ 中的对应物却可以正常工作并且 returns S_OK.
C:

isOk = pD3D->lpVtbl->CreateDevice(pD3D, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3dpParams.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpParams, &lpDevice);

C++:

isOk = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3dpParams.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpParams, &lpDevice);

我的猜测在于D3DPRESENT_PARAMETERS d3dpParams 在 C++ 中,它用 "= {}" 初始化:

D3DPRESENT_PARAMETERS d3dpParams = {};
d3dpParams.Windowed = false;
d3dpParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
...

而在 C 中你只能写“;”:

D3DPRESENT_PARAMETERS d3dpParams;
d3dpParams.Windowed = false;
d3dpParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
...

*pD3D 是由 Direct3DCreate9() 创建的 IDirect3D9*,如果我理解正确,它不会失败。

最初是用 gcc 完成的,但是 msvc 给出了完全相同的结果。

普通 C 结构的 ={} 初始化仅将内存清零。

Microsoft 在 https://docs.microsoft.com/en-us/windows/win32/direct3d9/creating-a-device 的示例为此建议 ZeroMemory

D3DPRESENT_PARAMETERS d3dpp; 

ZeroMemory( &d3dpp, sizeof(d3dpp) );

C 版本不起作用的根本原因是:

D3DPRESENT_PARAMETERS d3dpParams;

创建一个名为 d3dpParams 的未初始化变量。由于它是未初始化的,因此 CreateDevice 函数正在读取各个成员设置的任何垃圾数据,从而导致不稳定的行为。你会在 C++ 中遇到同样的问题,所以这不是真正的 C 与 C++ 问题。

由于问题之一是初始化,C++ 代码通过使用 {} 语法将结构中的所有元素设置为 0 来进行初始化。

由于C没有这样的语法来初始化一个变量,你需要将所有成员设置为0。函数 ZeroMemorymemset 和类似的 C 函数可用于执行此操作。

ZeroMemory(&d3dpParams, sizeof(d3dpParams));

C++ 中的零初始化器是:

D3DPRESENT_PARAMETERS d3dpParams = {};

C 中等效的初始值设定项是:

D3DPRESENT_PARAMETERS d3dpParams = {0};

您不必致电 ZeroMemorymemset。请注意,使用符合标准的 C 编译器时,C++ 版本将生成编译器警告,因为 C 中不允许使用空的初始值设定项。这就是为什么需要“0”的原因。