Using Cards.dll

Started by
8 comments, last by badmoon 19 years, 6 months ago
Has anyone used the cards.dll dll that Windows uses for its card games? I fancied writing my own card game, and wanted to do it using cards.dll. I've kind of got it working, but a problem seems to occur with how the stack pointer is restored when calling a function from the dll. Basically as with any ordinary function before calling it you push the parameters onto the stack. Once the function returns there is an add instruction to bring the stack pointer back to what it was before the parameters were pushed. However, when calling a function from the dll it will restore the stack pointer before returning. So the add instruction after it will make the stack pointer too large - this leads to an exception being thrown. Here's my code for using cards.dll:

typedef BOOL _declspec(dllexport) (*FUNC_TYPE_1)( int* pnSizex, int* pnSizey );

HINSTANCE ghCardDLL;
FUNC_TYPE_1 gpfnCDTInit;

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nShowCmd )
{
	int nCardw, nCardh;

	ghCardDLL = LoadLibrary( "Cards.dll" );
	gpfnCDTInit = (FUNC_TYPE_1)GetProcAddress( mhCardDLL, "cdtInit" );
	gpfnCDTInit( &nCardw, &nCardh ); //<------EXCEPTION WHEN FUNCTION RETURNS
	...
}




Does anybody know what's going wrong here?
Advertisement
Have you read the msdn article on it? It looks as though they're using a lib / .h to 'statically' link to the DLL, is this possible in your case?
I would prefer to use it dynamically if it's possible at all.

But how do you statically link to a dll?

Excuse my naivity here, as I'm quite new to DLLs. I did visit that site you mentioned but the project seems to be created in a version earlier to Visual C++ 6.
Sounds like it might be a "calling convention" problem. Check if the functions are "C convention" (I believe cdecl is the keyword used) or if they're "standard calling convention" (stdcall). I don't remember the exact details of declaring a function to use a different calling convention, but I think it's something like this:

void dllexport(stdcall) DoSomethingCool(int gnarly);



Hopefully that points you in the right direction
To statically link to a DLL, you have to have .lib and header files that match the DLL. Then you simply link statically with the .lib file, and #include the header, and it should all magically work as if the functions in the DLL are part of your application.

The AP also has a good point - Cards.dll being quite old, there's a good chance that it uses the WINAPI calling convention (which was the same as the pascal calling convention, which iirc Windows 2.0 and below were written in).

Any clues in the header file from that website?
I did look at the header file and they are declared as follows:

BOOL _declspec(dllexport) cdtInit(int FAR *pdxCard, int FAR *pdyCard);


However, as I am linking dynamically I need to retrieve the functions from the dll using GetProcAddress, and store them in a function pointer that has the matching type. Which means I need to delcare my function pointer like so:

BOOL _declspec(dllexport) (*cdtInit)(int FAR *pdxCard, int FAR *pdyCard);


But my compiler throws fits at this - It thinks I'm just declaring a function and gives a linker error saying the symbol cdtInit has not been defined. I would really like to get this to work. Please help.

And, regarding the static linking, can you explain how you mean the lib and the header need to match the dll. I can see how you could get the header to match but if the lib contains the exact functions that are in the dll, then that means I know how to implement the functions so what would be the point in using the dll? Please clear up my confusion here.


Cool! I've got it working and in a rather sly kind of way too. Since VC was calling the functions incorrectly I wrote my own assembly code to call them:

So instead of calling the dll function like this:

gpfnCDTInit( &nCardX, &nCardY );

I actually use the following assembly instructions:

	__asm 	{		mov		esi, esp;		push		offset nCardX;		push		offset nCardY;		call		dword ptr [gpfnCDTInit];	}


If anyone could suggest an alternative way of doing this, I'd still like to hear it. Plus I'd also like some elaboration on that static linking method, if possible.

Thanks
Yeah, because when creating a pointer to a function there is no need for __declspec(dllexport).
"C lets you shoot yourself in the foot rather easily. C++ allows you to reuse the bullet!"
http://www.catch22.net/tuts/cardtut.asp
Thanks AP, that was exactly what I was looking for

This topic is closed to new replies.

Advertisement