Reputation: 45
i have to admit that i have really strange issue, which im not able to solve by my self. Im trying from few days without success.
My goal is to use Direct3DEx interfaces from C (not C++). I cant use Direct3D because i have to deal with shared resource handles with surfaces from different d3ddevices.
I have no any problems with creating IDirect3DEx from C++, works perfectly. For example this code works as expected
IDirect3D9Ex* m_d3d;
Direct3DCreate9Ex(D3D_SDK_VERSION, &m_d3d);
UINT c = m_d3d->GetAdapterCount();
m_d3d->Release();
Now im trying to do exactly the same from C,
my code is:
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);
}
i dont see absolutly any reason why this piece of code doesnt work.
Please notice that code line:
hr = Direct3DCreate9ExFunc(D3D_SDK_VERSION, &pDirect3D9ExInterface);
returns S_OK, and when im checking pDirect3D9ExInterface pointer under debuger it looks like a valid pointer.
But this line of code:
count = IDirect3D9Ex_GetAdapterCount(pDirect3D9ExInterface); //crash
causes my program to crash. When im switching my DirectX9 to debug mode, on VS output window i see after crash, something like this:
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.
Additionaly if i change this C code to Direct3D initialization (no Direct3DEx) than works without any problems.
What im doing wrong? Where is the catch?
thanks in advance
Jakub
Upvotes: 0
Views: 1028
Reputation: 7835
This seems to be due to a bug in the definition of the d3d9.h
header file.
A function seems to be left out of the IDirect3D9Ex
interface that appears in the IDirect3D9
interface (IDirect3D9Ex
inherits from IDirect3D9
).
In c++
this still works because of inheritance and virtual functions working correctly, in c
, it doesn't correctly pick up the inheritance due to the way their v-tables are constructed.
Below I've commented out the line that needs to be added to fix this issue (in d3d9.h at line 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;
You can double check that the functions line up correctly with the returned interface by loading the d3d9.dll
symbols from the MS servers and comparing the names in the v-table with the values reported. In the image below, the left hand side is the v-table before being fixed, and the right hand side is the v-table after being fixed.
To get the symbol's from the MS symbol servers:
LoadLibrary("d3d9.dll")
has been calledDebug
->Windows
->Modules
)d3d9.dll
in the modules list (try typing d3d9.dll
to quickly go to it)d3d9.dll
and click on Load Symbols From
->Microsoft Symbol Servers
Upvotes: 2