Sign in to follow this  
badmoon

Using Cards.dll

Recommended Posts

badmoon    122
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?

Share this post


Link to post
Share on other sites
badmoon    122
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.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
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

Share this post


Link to post
Share on other sites
fractoid    703
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?

Share this post


Link to post
Share on other sites
badmoon    122
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.


Share this post


Link to post
Share on other sites
badmoon    122
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

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this