Question on DLL use (non-chess)

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

User avatar
hgm
Posts: 27808
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Question on DLL use (non-chess)

Post by hgm »

A friend of me has bought a piece of data-acquisition hardware that connects to a PC through a USB port. He is not an experienced programmer, so I offered to help him to get it running. But I run into problems that are beyond me as well.

The hardwre comes with a disk that contains drivers in a DLL file. A manual gives the name of the routine, and there are several examples included. But they are all for compilers I do not have (and neither does my friend): VC6, VC2005, VB, Delphi.

Now I thought that DLLs were machine-language programs with a standard interface, so that any language that supports DLLs can use the same DLLs. Before this I used a DLL exacty once in my life. It seemed simple enough: I loaded the DLL by calling LoadLibrary(), and then I requested a pointer to the routine I want to call with GetProcAddress().

When I try the same now, however, I can load the DLL (the handle returned by LoadLibrary() is non-NULL), but none of the names of the driver routines described in the manual can be found by GetProcAddr(). (It always returns 0).

Now there is a .lib file with the same name as the DLL. Some texts I googled up seem to suggest that the address information on the entry points might be in there. (I could not fully understand what they were saying.) But I am not sure how to use this .lib file. I am using gcc. A .lib sounds like it is a static linking library. But the object file format of gcc and VC2005 is not compatible, is it? So I cannot simply link the .lib file to the rest of my sources.

I am not even sure how VC2005 uses the .lib file. There is no make file, so I guess this information is hidden in the .vcproj file. Altough this is a text file, I have no idea what all the stuff in there means.

Can anyone help me, by explaining me how I should use the .lib file with gcc, or how I can otherwise find out the addresses of the driver routines in the DLL?
Dann Corbit
Posts: 12541
Joined: Wed Mar 08, 2006 8:57 pm
Location: Redmond, WA USA

Re: Question on DLL use (non-chess)

Post by Dann Corbit »

If you link against the library, that will give you the entry points.
You should also have a header file (.h).

If dynamic loading is not working, then something is wrong, because that method should work also.

The first thing to do is get the module handle something like this:

Code: Select all

#ifdef  WIN32
             	hOracleDll = GetModuleHandle("OCI.DLL");
#else
  #if defined(HPUX) && ! defined(ITANIUM)
				hOracleDll = LoadLibrary("libclntsh.sl");
  #else
				hOracleDll = LoadLibrary("libclntsh.so");
  #endif
#endif

[code]

and then collect the proc addresses that you need something like this:

[code]
   fnOCIEnvCreate = (pfnOCIEnvCreate)GetProcAddress(hOracleDll, "OCIEnvCreate");
   fnOCITerminate = (pfnOCITerminate)GetProcAddress(hOracleDll, "OCITerminate");
[/code]
where the function pointers have the correct signature for the function type.  You get the signature for the function pointers by examination of the supplied header file.
User avatar
hgm
Posts: 27808
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Question on DLL use (non-chess)

Post by hgm »

With code similar to what you wrote above, without linking against the .lib, I crash because of calling a NULL pointer. (GetProcAddress returns 0.)

Can GCC link against a library that is meant for VC2005?

If I fail to link to a library that I need, I would have expected to get 'undefined references' messages during the linking. If I have no undefined references from the exlicitly mentioned files, why would the linker include any modules from the library?
Dann Corbit
Posts: 12541
Joined: Wed Mar 08, 2006 8:57 pm
Location: Redmond, WA USA

Re: Question on DLL use (non-chess)

Post by Dann Corbit »

hgm wrote:With code similar to what you wrote above, without linking against the .lib, I crash because of calling a NULL pointer. (GetProcAddress returns 0.)

Can GCC link against a library that is meant for VC2005?
No problem if it is Mingw GCC.
I have no idea what will happen with Cygwin.

If I fail to link to a library that I need, I would have expected to get 'undefined references' messages during the linking. If I have no undefined references from the exlicitly mentioned files, why would the linker include any modules from the library?
Dann Corbit
Posts: 12541
Joined: Wed Mar 08, 2006 8:57 pm
Location: Redmond, WA USA

Re: Question on DLL use (non-chess)

Post by Dann Corbit »

Dann Corbit wrote:
hgm wrote:With code similar to what you wrote above, without linking against the .lib, I crash because of calling a NULL pointer. (GetProcAddress returns 0.)

Can GCC link against a library that is meant for VC2005?
No problem if it is Mingw GCC.
I have no idea what will happen with Cygwin.

If I fail to link to a library that I need, I would have expected to get 'undefined references' messages during the linking. If I have no undefined references from the exlicitly mentioned files, why would the linker include any modules from the library?
When you dynamically load, you have to check the returns yourself, and there is no such thing as an unresolved external if you dynamically load the function pointer.
CThinker
Posts: 388
Joined: Wed Mar 08, 2006 10:08 pm

Re: Question on DLL use (non-chess)

Post by CThinker »

hgm wrote:A friend of me has bought a piece of data-acquisition hardware that connects to a PC through a USB port. He is not an experienced programmer, so I offered to help him to get it running. But I run into problems that are beyond me as well.

The hardwre comes with a disk that contains drivers in a DLL file. A manual gives the name of the routine, and there are several examples included. But they are all for compilers I do not have (and neither does my friend): VC6, VC2005, VB, Delphi.

Now I thought that DLLs were machine-language programs with a standard interface, so that any language that supports DLLs can use the same DLLs. Before this I used a DLL exacty once in my life. It seemed simple enough: I loaded the DLL by calling LoadLibrary(), and then I requested a pointer to the routine I want to call with GetProcAddress().

When I try the same now, however, I can load the DLL (the handle returned by LoadLibrary() is non-NULL), but none of the names of the driver routines described in the manual can be found by GetProcAddr(). (It always returns 0).

Now there is a .lib file with the same name as the DLL. Some texts I googled up seem to suggest that the address information on the entry points might be in there. (I could not fully understand what they were saying.) But I am not sure how to use this .lib file. I am using gcc. A .lib sounds like it is a static linking library. But the object file format of gcc and VC2005 is not compatible, is it? So I cannot simply link the .lib file to the rest of my sources.

I am not even sure how VC2005 uses the .lib file. There is no make file, so I guess this information is hidden in the .vcproj file. Altough this is a text file, I have no idea what all the stuff in there means.

Can anyone help me, by explaining me how I should use the .lib file with gcc, or how I can otherwise find out the addresses of the driver routines in the DLL?
My suggestion is for you to search the web for "DLL export viewer". Look for utilities that will allow you to view the functions (names) that are exported by a DLL. Verify this against the function name that you are passing to GetProcAddress().
User avatar
hgm
Posts: 27808
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Question on DLL use (non-chess)

Post by hgm »

OK, this DLL export viewer was a great idea. Many thanks for that. The problem turned out to be that names which in the manual occurred as xxx, would have entry points in the DLL under the name _xxx@4. I had been smart enough to try the underscore, but not the suffix. This apparently indicates the number of bytes in the arguments.

Now I run into the following problem, however:

The routines in the DLL seem to all pop their arguments from the machine stack before returning. My compiler (gcc) expects routines to leave the stack untouched. This of course leads to a quick crash fter a certan number of calls to the DLL.

Is this incompatible calling sequence a consequence of a wrong declaration of the DLL routines? I am using

const void *(__cdecl *RoutineName)()

now. Is there another declaration possible that would make gcc aware that this is a routine that messes up the stack, so that it adapts its callng code to it?
User avatar
Zach Wegner
Posts: 1922
Joined: Thu Mar 09, 2006 12:51 am
Location: Earth

Re: Question on DLL use (non-chess)

Post by Zach Wegner »

Are you sure you don't have it backwards? According to this: http://msdn.microsoft.com/en-us/library ... S.71).aspx

__cdecl means the function is in charge of cleaning up the stack, and __stdcall leaves it mangled. I would try __stdcall though.
Teemu Pudas
Posts: 88
Joined: Wed Mar 25, 2009 12:49 pm

Re: Question on DLL use (non-chess)

Post by Teemu Pudas »

_xxx@4
__stdcall.
User avatar
hgm
Posts: 27808
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Question on DLL use (non-chess)

Post by hgm »

You re right. That was the problem, and the solution I was looking for. I did not have anything backwards or forwards, as I did not know anything at all. I just adapted the only thing that I had working, without knowing why. Which happened to use a DLL with another calling convntion (where I was not even aware that multiple calling conventions existed).

But everything starts to become clear now!

Thanks for the advice, everyone!