我不得不承认,我有一个很奇怪的问题,我自己无法解决。我试了几天都没有成功。
我的目标是使用C(非C++)的DICT3DEX接口。我不能使用Direct3D,因为我必须处理来自不同D3D设备的曲面的共享资源句柄。
我没有任何问题,从iCix3DEX从C++,工作完美。例如,此代码按预期工作

IDirect3D9Ex* m_d3d;

Direct3DCreate9Ex(D3D_SDK_VERSION, &m_d3d);

UINT c = m_d3d->GetAdapterCount();

m_d3d->Release();

现在我试着用C做同样的事情,
我的代码是:
void *pd3dll = (void *) LoadLibrary("d3d9.dll");
 UINT count;
 IDirect3D9Ex *pDirect3D9ExInterface;
 HRESULT hr;

 typedef HRESULT (WINAPI *Direct3DCreate9Ex_t)(UINT SDKVersion, IDirect3D9Ex **ppD3D);

 Direct3DCreate9Ex_t Direct3DCreate9ExFunc;

 Direct3DCreate9ExFunc = (Direct3DCreate9Ex_t) GetProcAddress((HMODULE) pd3dll, "Direct3DCreate9Ex");

 hr = Direct3DCreate9ExFunc(D3D_SDK_VERSION, &pDirect3D9ExInterface);

 if (SUCCEEDED(hr))
 {
    count = IDirect3D9Ex_GetAdapterCount(pDirect3D9ExInterface); //crash

    IDirect3D9Ex_Release(pDirect3D9ExInterface);
 }

我不明白为什么这段代码不起作用。
请注意代码行:
hr = Direct3DCreate9ExFunc(D3D_SDK_VERSION, &pDirect3D9ExInterface);

返回S_OK,当im在debuger下检查pDirect3D9ExInterface指针时,它看起来像一个有效的指针。
但这一行代码:
count = IDirect3D9Ex_GetAdapterCount(pDirect3D9ExInterface); //crash

导致我的程序崩溃。当我将DirectX9切换到调试模式时,在VS输出窗口中,我在崩溃后看到如下内容:
Direct3D9:(错误):指定的初始化函数无效。RegisterSoftwareDevice失败。
运行时检查失败#0-ESP的值未通过函数调用正确保存。这通常是调用使用一个调用约定声明的函数以及使用另一个调用约定声明的函数指针的结果。
另外,如果我将此C代码更改为Direct3D初始化(没有Direct3DEx),则可以正常工作。
我做错什么了?抓到什么了?
提前谢谢
雅库布

最佳答案

这似乎是由于d3d9.h头文件定义中的错误造成的。
IDirect3D9Ex接口中出现的IDirect3D9接口中似乎遗漏了一个函数(IDirect3D9Ex继承自IDirect3D9)。
c++中,由于继承和虚函数工作正常,它仍然可以工作;在c中,由于v表的构造方式,它不能正确地获取继承。
下面我已经注释掉了修复此问题需要添加的行(在第2044行的d3d9.h中):

DECLARE_INTERFACE_(IDirect3D9Ex, IDirect3D9)
{
    /*** IUnknown methods ***/
    STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE;
    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
    STDMETHOD_(ULONG,Release)(THIS) PURE;

    /*** IDirect3D9 methods ***/
    //Add this here: STDMETHOD(RegisterSoftwareDevice)(THIS_ void* pInitializeFunction) PURE;
    STDMETHOD_(UINT, GetAdapterCount)(THIS) PURE;
    STDMETHOD(GetAdapterIdentifier)(THIS_ UINT Adapter,DWORD Flags,D3DADAPTER_IDENTIFIER9* pIdentifier) PURE;
    STDMETHOD_(UINT, GetAdapterModeCount)(THIS_ UINT Adapter,D3DFORMAT Format) PURE;
    STDMETHOD(EnumAdapterModes)(THIS_ UINT Adapter,D3DFORMAT Format,UINT Mode,D3DDISPLAYMODE* pMode) PURE;

通过从MS服务器加载d3d9.dll符号并将v表中的名称与报告的值进行比较,可以再次检查函数是否与返回的接口正确对齐。下图中,左侧为固定前的v形台,右侧为固定后的v形台。
c - 从C创建Direct3DEx接口(interface)不起作用-LMLPHP
要从MS symbol服务器获取符号:
启动应用程序并在调用LoadLibrary("d3d9.dll")之后放置断点
打开“模块”窗口(从菜单栏中)
在模块列表中找到Debug(尝试键入Windows以快速转到它)
右键单击Modules,然后单击d3d9.dll>d3d9.dll
等待几秒钟,让它下载并加载符号,然后地址应该解析为有用的名称。

关于c - 从C创建Direct3DEx接口(interface)不起作用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35542632/

10-17 01:54