CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 27

Thread: [RESOLVED] DLL exported functions

  1. #1
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,592

    [RESOLVED] DLL exported functions

    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

  2. #2
    Join Date
    Jul 2002
    Posts
    2,543

    Re: DLL exported functions

    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.

  3. #3
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,592

    Re: DLL exported functions

    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

  4. #4
    Join Date
    Jul 2002
    Posts
    2,543

    Re: DLL exported functions

    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.

  5. #5
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,592

    Re: DLL exported functions

    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

  6. #6
    Join Date
    Oct 2005
    Location
    Minnesota, U.S.A.
    Posts
    680

    Re: DLL exported functions

    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.

    Good Luck,
    -Erik

  7. #7
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,592

    Re: DLL exported functions

    Many thanks for the explanation Erik. The only bit I didn't understand was this:-

    Quote Originally Posted by egawtry View Post
    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

  8. #8
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,592

    Re: DLL exported functions

    ...oh, and this too :-

    Quote Originally Posted by egawtry View Post
    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

  9. #9
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,607

    Re: DLL exported functions

    Quote Originally Posted by John E View Post
    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
    Code:
    D:\Temp\24>exports 24dll.dll
    ModuleType:
      PE executable (DLL)
    Subsystem:
      Win32 GUI
    ModuleName:
      24dll.dll
    Exported Info: BaseOfOrdinals    = 1
                   NumberOfNames     = 2
                   NumberOfFunctions = 2
    
      RelVirtAddr  Ord  Hint   ExportedFuncName
    
      0x00001000     1     0   foo1
      0x00001030     2     1   foo2
    
    D:\Temp\24>exports 24dll_noname.dll /f
    ModuleType:
      PE executable (DLL)
    Subsystem:
      Win32 GUI
    ModuleName:
      24dll_noname.dll
    Exported Info: BaseOfOrdinals    = 2
                   NumberOfNames     = 1
                   NumberOfFunctions = 2
    
      RelVirtAddr  Ord  Hint   ExportedFuncName
    
      0x00001000     2     1   (null)
      0x00001030     3     0   foo2
    
    D:\Temp\24>exports 24dll_noname.2.dll /f
    ModuleType:
      PE executable (DLL)
    Subsystem:
      Win32 GUI
    ModuleName:
      24dll_noname.dll
    Exported Info: BaseOfOrdinals    = 3
                   NumberOfNames     = 1
                   NumberOfFunctions = 2
    
      RelVirtAddr  Ord  Hint   ExportedFuncName
    
      0x00001000     3     1   (null)
      0x00001030     4     0   foo2
    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   
    ---------------------------
    Attached Files Attached Files
    Last edited by Igor Vartanov; January 4th, 2012 at 02:09 PM.
    Best regards,
    Igor

  10. #10
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,607

    Re: DLL exported functions

    Quote Originally Posted by egawtry
    4. Don't forget the WINAPI in the declaration! This makes it compatible with all compilers.
    ...and introduces a very special name mangling in case of VC++, if no DEF in use.

    Code:
    #include <windows.h>
    
    extern "C" __declspec(dllexport)
    void WINAPI foo1() 
    {
    }
    
    extern "C" __declspec(dllexport)
    void foo2() 
    {
    }
    Code:
    D:\Temp\25>exports 25dll.dll
    ModuleType:
      PE executable (DLL)
    Subsystem:
      Win32 GUI
    ModuleName:
      25dll.dll
    Exported Info: BaseOfOrdinals    = 1
                   NumberOfNames     = 2
                   NumberOfFunctions = 2
    
      RelVirtAddr  Ord  Hint   ExportedFuncName
    
      0x00001000     1     0   _foo1@0
      0x00001010     2     1   foo2
    Last edited by Igor Vartanov; January 4th, 2012 at 02:16 PM.
    Best regards,
    Igor

  11. #11
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,592

    Re: DLL exported functions

    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

  12. #12
    Join Date
    Oct 2005
    Location
    Minnesota, U.S.A.
    Posts
    680

    Re: DLL exported functions

    Quote Originally Posted by John E View Post
    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.

    -Erik

  13. #13
    Join Date
    Oct 2005
    Location
    Minnesota, U.S.A.
    Posts
    680

    Re: DLL exported functions

    Quote Originally Posted by John E View Post
    Can VC++ actually generate a .DEF file at build time? I've never needed to do it but am just curious.

    There are 3rd party programs to do this, but most people just dynamically export functions with _dllexport if they are too lazy to use a DEF file.


    Quote Originally Posted by Igor Vartanov View Post
    ...and introduces a very special name mangling in case of VC++, if no DEF in use.
    That is why I ALWAYS use a DEF file.


    -Erik

  14. #14
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,592

    Re: DLL exported functions

    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

  15. #15
    Join Date
    Oct 2005
    Location
    Minnesota, U.S.A.
    Posts
    680

    Re: DLL exported functions

    Quote Originally Posted by John E View Post
    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


    -Erik

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width




On-Demand Webinars (sponsored)