从 C 创建 Direct3DEx 接口不起作用

Create Direct3DEx interface from C doesn't work

我不得不承认我有一个非常奇怪的问题,我无法自己解决。我从几天开始尝试但没有成功。

我的目标是使用来自 C(而非 C++)的 Direct3DEx 接口。我不能使用 Direct3D,因为我必须处理来自不同 d3d 设备的表面的共享资源句柄。

我从 C++ 创建 IDirect3DEx 没有任何问题,工作完美。例如,此代码按预期工作

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);  

returns S_OK,当我在调试器下检查 pDirect3D9ExInterface 指针时,它看起来像一个有效指针。
但是这行代码:

count = IDirect3D9Ex_GetAdapterCount(pDirect3D9ExInterface); //crash  

导致我的程序崩溃。当我将我的 DirectX9 切换到调试模式时,在 VS 输出 window 我看到崩溃后,像这样:

Direct3D9: (ERROR) :Invalid initialization function specified. RegisterSoftwareDevice fails. Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.

此外,如果我将此 C 代码更改为 Direct3D 初始化(无 Direct3DEx),则可以正常工作。
我做错了什么?问题在哪里?
提前致谢
雅库布

这似乎是由于 d3d9.h 头文件定义中的一个错误。 IDirect3D9Ex接口中似乎遗漏了一个函数,出现在IDirect3D9接口中(IDirect3D9Ex继承自IDirect3D9)。

c++ 中,由于继承和虚函数正常工作,这仍然有效,在 c 中,由于 v-[=55= 的方式,它无法正确获取继承] 已构建。

下面我注释掉了需要添加以解决此问题的行(在 d3d9.h 的第 2044 行):

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-table 中的名称与报告的值进行比较来仔细检查函数是否与返回的接口正确对齐。下图中,左边是修复前的v-table,右边是修复后的v-table

要从 MS 符号服务器获取符号:

  • 启动应用程序并在 LoadLibrary("d3d9.dll") 被调用后放置一个断点
  • 打开 'Modules' window(从菜单栏 Debug->Windows->Modules
  • 在模块列表中找到 d3d9.dll(尝试键入 d3d9.dll 以快速找到它)
  • 右击d3d9.dll然后点击Load Symbols From->Microsoft Symbol Servers
  • 等待几秒钟以下载并加载符号,然后地址应解析为有用的名称。