Linking d3dx with Visual Studio

Started by
5 comments, last by Evil Steve 16 years, 4 months ago
Hey all, I'm having a strange problem building the code from the book Programming a Multiplayer FPS in DirectX. I did a little modification on the game and I compiled the code on two separate computers (both had project files that came with the cd, so i didn't configure the projects), so compilation of both mostly the same. But when I compiled the release build on one computer, it produced a larger executable (about 1meg) and ran without errors when run on a clean XP service pack 2 computer. However, compiled on the other computer, it produces a smaller executable (200kb) and gives an error message saying it couldn't find d3dx9_30.dll. What could be the reason for this? Is there some compiler settings? Could it be that the computer that works has the DirectX 9.0c October 2004 SDK but the other has a much more recent version? Any ideas would be great
Advertisement
Did you check to make sure you're compiling against the release version of the library (that's d3dx9.lib, not d3dx9d.lib )
Yep, they're both d3dx9.lib
There are a few possible reasons for the two differences, and they may not be related.

Folklore has it that there was once a DirectX SDK release (a December, IIRC) that offered only a static D3DX library. Contrast this with the more recent SDKs, which offer no static library. If you happen to have linked one of the programs statically to D3DX, the executable will be a fair deal bigger, and will have no dependency on a d3dx9_*.dll, whereas the alternative output would be smaller and will require the DLL to run. Notably, you can't tell which version of the library the program will link against just by looking at the code, as the resident SDK directs your reference to 'd3dx.lib' to whatever version pertains to it, at compile-time.

That's just one possibility, but the reasons for the size difference almost certainly has something to do with linking. Static linking will always produce a bigger executable, but exactly what it is that is linking differently is anybody's guess. I'd recommend you also take a look to see how the Visual C++ runtime is being linked in each case.

Also, just because one program demands a D3DX and the other doesn't, you can't deduce that the latter is linked statically, as these D3DX libraries are not backward-compatible. If you take a look in your %sysroot%/system32 you'll see a collection of d3dx9_*.dlls with a fairly arbitrary set of numbers following them. Any DirectX installation will place its D3DX version here, but won't add any others. For this reason, you can't guarantee the existence of any D3DX DLL unless you have installed a runtime with exactly that version (and not simply a later one, as you might expect).
Ring3 Circus - Diary of a programmer, journal of a hacker.
Hmm, we'll I'd guess that it's due to the two different version of the DirectX SDK, which is interesting.. If that's the case, I feel like I'd rather build with the older SDK to make distribution simple.
Quote:Original post by MilfredCubicleX
Hmm, we'll I'd guess that it's due to the two different version of the DirectX SDK, which is interesting.. If that's the case, I feel like I'd rather build with the older SDK to make distribution simple.

I hear that.

Does anyone know why MS refuse to offer a static D3DX build?
Ring3 Circus - Diary of a programmer, journal of a hacker.
Quote:Original post by TheAdmiral
Does anyone know why MS refuse to offer a static D3DX build?
Security reasons. DLLs can be patched with Windows Update if for instance a vulnerability is found in the JPEG loading code, whereas statically linked code can't. That's the same reason it's against the EULA to include the D3DX DLL in a download; if it ends up in the application directory, then Windows Update won't know to patch it, so if a vulnerability is found, the version of the DLL in the Windows directory will be patched, but the version in the application directory (Which will be loaded by the EXE) won't be.


Quote:Original post by MilfredCubicleX
Hmm, we'll I'd guess that it's due to the two different version of the DirectX SDK, which is interesting.. If that's the case, I feel like I'd rather build with the older SDK to make distribution simple.
I'd highly recommend going with the most recent D3DX version if you use ID3DXFont or ID3DXSprite. They've been improved since the D3DX library was DLLified. There's bound to be other performance enhancements too. If you're just distributing your app to friends and people you know, I'd be inclined to say just package the DLL with your exe. If it's going on a website, you could include a link to the D3DX runtime on microsoft.com.

Alternatively, you could delay load the D3DX DLL, so you can display a friendly error to the user if it's missing (Which is what I do). Code snippet time:
#include <windows.h>#include <delayimp.h>#include <d3dx9.h>#ifdef _DEBUG#	pragma comment(lib, "d3dx9d.lib")#else#	pragma comment(lib, "d3dx9.lib")#endif//============================================================================// Structured Exception Handler for delay loaded DLLsstatic LONG WINAPI DelayLoadDllExceptionFilter(PEXCEPTION_POINTERS pep, std::wstring& strError){	// If this is a Delay-load problem, ExceptionInformation[0] points 	// to a DelayLoadInfo structure that has detailed error info	PDelayLoadInfo pdli = PDelayLoadInfo(pep->ExceptionRecord->ExceptionInformation[0]);	wchar_t szBuff[512];	switch(pep->ExceptionRecord->ExceptionCode)	{	case VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND):		_snwprintf(szBuff, sizeof(szBuff)/sizeof(wchar_t), L"Could not find \"%S\"", pdli->szDll);		strError = szBuff;		return EXCEPTION_EXECUTE_HANDLER;	case VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND):		// The DLL was found but it doesn't contain the function		if(pdli->dlp.fImportByName)		{			_snwprintf(szBuff, sizeof(szBuff)/sizeof(wchar_t), L"Could not find \"%S\" in \"%S\"",				pdli->dlp.szProcName, pdli->szDll);		}		else		{			_snwprintf(szBuff, sizeof(szBuff)/sizeof(wchar_t), L"Could not find function ordinal %d in \"%S\"",				pdli->dlp.dwOrdinal, pdli->szDll);		}		strError = szBuff;		return EXCEPTION_EXECUTE_HANDLER;	default:		// We don't recognize this exception  		return EXCEPTION_CONTINUE_SEARCH;		break;	}}//============================================================================// Load D3DX DLL by calling one of its functionsstatic bool InitD3DX(std::wstring& strError){	bool bRet = true;	__try	{		// Do a simple matrix multiply		D3DXMATRIXA16 m1, m2, m3;		memset(&m1, 0, sizeof(m1));		memset(&m2, 0, sizeof(m2));		D3DXMatrixMultiply(&m3, &m1, &m2);	}	__except (DelayLoadDllExceptionFilter(GetExceptionInformation(), strError))	{		bRet = false;	}	return bRet;}
Then to flag the D3DX DLL as needing delay loaded, go to project settings -> Linker -> Input -> Delay Loaded DLLs, and add "d3dx9d_35.dll" (no quotes), or whatever the DLL name of the version you're linking to is (You can run depends.exe (comes with the platform SDK) on your compiled exe to find out what DLL version it's using) - Assuming VC2005. Other versions should be similar though.

[Edited by - Evil Steve on December 6, 2007 1:55:15 PM]

This topic is closed to new replies.

Advertisement