As far as I understand, a DLL's exported function table can contain either function names or ordinal numbers (perhaps both). When an exe gets launched, how does Windows match it up to the functions in the DLL? Does it start by searching for a matching function name, then, if it doesn't find one, match the ordinal numbers somehow?
The reason I'm asking is that our (VC built) app links to a DLL built using MinGW. Every time the MinGW developer brings out a new version, our app stops working (with Windows putting up a message box about missing ordinals in his updated DLL). The MinGW developer isn't building with reference to a .DEF file so I'm guessing that might be part of the problem.
Having said that, all his exported functions are standard 'C' functions - so unless MinGW is decorating them, I'd expect them to be found if Windows starts off by trying to match the function names. Hope this makes sense!
[Edit...] Or is this something I need to specify at link time? Do I need to link our exe so that it'll load functions in his DLL by name, rather than by number?
Last edited by John E; January 4th, 2012 at 07:25 AM.
"A problem well stated is a problem half solved.” - Charles F. Kettering
AFAIK, if your application is linked to third-party dll through .lib file, you need to rebuild this application with new .lib. Otherwise, I think, it is undefined behavior.
If you need to have runtime compatibility with different third-party dll versions, use LoadLibrary/GetProcAddress technique.
Thanks Alex. Something new has just come to light....
I've noticed that in the 3rd-party DLL, plain 'C' functions seem to be getting exported with a leading underscore. So for example, the function jack_client_open is getting exported as _jack_client_open (note the prepended underscore). I wonder if this is causing the ordinal values to get chosen at run time, instead of the function names?
In the back of my mind I remember once reading something about the significance of these leading underscores and how to turn them off. I'm blowed if I can remember the details though....
"A problem well stated is a problem half solved.” - Charles F. Kettering
All these details are handled by linker, when it works with a .lib file. I don't know much about this process, hopefully somebody else can say more.
I only know, this linking with a .lib file doesn't give forward compatibility with future dll versions. In such situation, immediate crash is the better thing that can happen.
Doesn't a .DEF file help with this though? I thought it allowed the exe to have fixed ordinal offsets for each of the exported functions. So as long as the ordinal values remain the same (and the function signature doesn't change) the original EXE should carry on working with the updated DLL. Or have I msunderstood it?
"A problem well stated is a problem half solved.” - Charles F. Kettering
On the DLL end:
1. Functions are exported by name. If no number is assigned to it, then one is arbitrarity assigned.
2. Functions can be exported by _dllexport, but if they are C functions, they will automatically have an underscore prepended (all C compilers do that). Also, watch out for C++ functions which have the arguments postpended.
3. DEF files, although MS is trying to get rid of them, is still the best way to export functions from a DLL. They are then portable between all compilers and the number may be specified.
4. Don't forget the WINAPI in the declaration! This makes it compatible with all compilers.
5. That being said, C++ classes exported from a DLL are almost impossible to use unless you have the matching class header and the SAME compiler. C++ does not work from the DEF file.
On the EXE end:
1. LIB files, built by IMPLIB, contain indexes to the locations of the functions inside the DLL. Any rebuild of the DLL requires a new LIB. If you have an old LIB, the linker will attempt to fix problems via the ordinal numbers, but changed function names or number representation will kill the build.
2. DLL functions may be dynamically imported with LoadLibrary and MakeProcInstance. This is actually the only way to use many older DLLs that have outdated LIB files from old compilers. It will also let your app run without the DLL present. If you aren't using a standard MS compiler, this is necessary. Some of the big compiler companies create their own type of LIB files (which are NOT compatible with the MS ones) that are built with a custom version of IMPLIB.
3. It used to be common to use an import DEF file (vs the DLL export one) and specify the ordinal numbers. That hasn't been used by anyone in a decade though.
=========
Looking at your issue, it appears that the MinGW compiler generates its own libraries, and since the DLL is rebuilt by the other C compiler, the custom LIB file from MinGW is then invalid. The functions from the DLL are probably dynamically exported (not using a DEF) and thus a recompile generates different ordinal number exports and invalidates the LIB.
You need to either:
1. Find the IMPLIB for your compiler/linker and rebuild the LIB file.
2. Dynamically link the DLL via LoadLibrary.
Many thanks for the explanation Erik. The only bit I didn't understand was this:-
Originally Posted by egawtry
Any rebuild of the DLL requires a new LIB. If you have an old LIB, the linker will attempt to fix problems via the ordinal numbers, but changed function names or number representation will kill the build.
Surely this would need to happen at run time? As long as the lib and its header files match each other, the exe build will always work just fine. The linker can't know if there's a more recent DLL available.
Which brings me back to the DEF file.... If the MinGW dev was building against a DEF file (and as long as he kept the same ordinal numbers for each build) there shouldn't be any need to rebuild the exe each time a new DLL gets built. For example, the system DLLs on my machine might not be the same as those on your machine. We might not even have the same OS's - but a given exe (say, Microsoft Excel) will run fine on both machines. I don't need to keep updating all my apps every time I do a system update.
"A problem well stated is a problem half solved.” - Charles F. Kettering
if they are C functions, they will automatically have an underscore prepended (all C compilers do that)
I'm sure I've read somewhere that there's a way to turn that off (and some circumstances when it's desirable to do so). Can't remember where I read it though....
[Edit...] Or does the underscore depend on the calling convention? I've definitely read something about this.....
[Edit 2...] I just looked it up on Wikipedia. A leading underscore without any other decoration is used by the _cdecl calling convention.
So that at least eliminates one mystery !
Last edited by John E; January 4th, 2012 at 12:55 PM.
"A problem well stated is a problem half solved.” - Charles F. Kettering
As far as I understand, a DLL's exported function table can contain either function names or ordinal numbers (perhaps both). When an exe gets launched, how does Windows match it up to the functions in the DLL? Does it start by searching for a matching function name, then, if it doesn't find one, match the ordinal numbers somehow?
It searches exactly for what has been provided in import library for the function prototype. If name, then it's name. If number, then it's number.
The reason I'm asking is that our (VC built) app links to a DLL built using MinGW. Every time the MinGW developer brings out a new version, our app stops working (with Windows putting up a message box about missing ordinals in his updated DLL). The MinGW developer isn't building with reference to a .DEF file so I'm guessing that might be part of the problem.
That's really weird, as the only way to suppress export name emission I'm aware of is DEF file. Though, I might be wrong here, need to refresh my knowledge of linker options.
Having said that, all his exported functions are standard 'C' functions - so unless MinGW is decorating them, I'd expect them to be found if Windows starts off by trying to match the function names. Hope this makes sense!
As I said, import section contains exactly what .lib file provided. So, it's more about .lib file generation rather than runtime issue.
[Edit...] Or is this something I need to specify at link time? Do I need to link our exe so that it'll load functions in his DLL by name, rather than by number?
Again, the only "something" at link time you operate with is .lib file, i.e. import library.
A simple demo attached.
There are three dll built from the same source three different ways
The first case is using no DEF file at all. There are both functions exported by names.
The second case is ordinals shifted, with foo1 name suppressed.
The third case is similar to second one but with ordinals shifted by two.
There are two EXEs built for corresponding dll versions (with corresponding .lib files). Now, in spite of seeming resemblance, 24dll_noname.2.dll been renamed cannot substitute 24dll_noname.dll because it has wrong ordinal for foo1.
Code:
---------------------------
24cln_noname.exe - Ordinal Not Found
---------------------------
The ordinal 2 could not be located in the dynamic link library 24dll_noname.dll.
---------------------------
OK
---------------------------
Last edited by Igor Vartanov; January 4th, 2012 at 02:09 PM.
Thanks for that very comprehensive reply Igor. I'm just about to try your examples but just out of curiosity... I know that I can use the linker's /DEF to specify a module definition file to be used while building a DLL but what about the other way aorund? Can VC++ actually generate a .DEF file at build time? I've never needed to do it but am just curious.
"A problem well stated is a problem half solved.” - Charles F. Kettering
Many thanks for the explanation Erik. The only bit I didn't understand was this:-
Surely this would need to happen at run time? As long as the lib and its header files match each other, the exe build will always work just fine. The linker can't know if there's a more recent DLL available.
True, it would link, but then immeadiately do the function missing popup when run. Sorry for the confusion, I was thinking of a special case.
Thanks guys, this has been really helpful. One more question if I may...
If I see this in a DEF file:-
Code:
foo1 @2
will the LIB / DLL tables contain BOTH the function name and the ordinal or just the ordinal? I'm assuming both - because I noticed in Igor's example that he specified this:-
Code:
foo1 @2 NONAME
which obviously prevents the name from getting exported. But what about the first case?
"A problem well stated is a problem half solved.” - Charles F. Kettering
Thanks guys, this has been really helpful. One more question if I may...
If I see this in a DEF file:-
Code:
foo1 @2
will the LIB / DLL tables contain BOTH the function name and the ordinal or just the ordinal? I'm assuming both - because I noticed in Igor's example that he specified this:-
Code:
foo1 @2 NONAME
which obviously prevents the name from getting exported. But what about the first case?
There are quite a few parameters that can be added to a DEF export, most of them unnecessary.
The NONAME is for the paranoid, I assume that Igor did it out of habit.
The most commonly used extension is to put PRIVATE in place of the ordinal number for predefined Windows exports like DllGetVersion().
Code:
EXPORTS ; Explicit exports can go here DllCanUnloadNow PRIVATE DllGetClassObject PRIVATE DllRegisterServer PRIVATE DllUnregisterServer PRIVATE ;DllRegisterServerCheck PRIVATE DllGetVersion PRIVATE
* The Best Reasons to Target Windows 8
Learn some of the best reasons why you should seriously consider bringing your Android mobile development expertise to bear on the Windows 8 platform.