CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 14 of 14
  1. #1
    Join Date
    Jun 2002
    Posts
    3

    Arrow Export dll functions with __stdcall and __cdecl

    Hello!
    I'm developing a dll with exported functions. I want to use the calling convention __stdcall. I also want to use the Explicit linking method in my application i e using LoadLibrary to load the dll in runtime and use GetProcAddress to get a pointer to the function I will call.

    I have made an application and a dll and everthing work nice and well, I can load the dll, I get my function pointer and perform the function calls as long as I use the calling convention __cdecl.

    But, when I then change to __stdcall I can load the dll but when I ask for function pointers I got null and I can't go further.

    My code is following.

    In application with __cdecl (works perfectly)
    -----------------------------------
    DllHandle = LoadLibrary("DllTest.dll");

    // declaration of function pointer
    int (__cdecl *pIntegerBackFunctionCdl)();
    int (__cdecl *pIntegerBackFunctionCdl2)(int);

    // asking for function pointers
    pIntegerBackFunctionCdl= (int (__cdecl *)())GetProcAddress( DllHandle , (LPCSTR)"IntegerBackFunction" );

    pIntegerBackFunctionCdl2= (int (__cdecl *)(int))GetProcAddress( DllHandle , (LPCSTR)"IntegerBackFunction2" );

    // call functions
    int RetVal1 = (*pIntegerBackFunctionCdl)();
    int RetVal2 = (*pIntegerBackFunctionCdl2)(1);

    ------------
    In the dll it looks as following:
    ------------

    // definition
    extern "C" {
    int __declspec(dllexport) __cdecl IntegerBackFunction(void);
    int __declspec(dllexport) __cdecl IntegerBackFunction2(int param1);
    }

    // implementation/declaration
    int __declspec(dllexport) __cdecl IntegerBackFunction(void){
    return 0x3;
    }
    int __declspec(dllexport) __cdecl IntegerBackFunction2(int param1){
    printf("param1=%d", param1);
    return 0x3;
    }

    ------------
    Above works perfectly!!


    But when I change to __stdcall as follows, it don't work!! I don't get any value to the functions, only null.
    ------------
    In application with __stdcall (DON'T WORK)
    ------------
    DllHandle = LoadLibrary("DllTest.dll");

    // declaration of function pointer
    int (__stdcall *pIntegerBackFunctionStd)();
    int (__stdcall *pIntegerBackFunctionStd2)(int);

    // asking for function pointers
    pIntegerBackFunctionStd= (int (__stdcall *)(void))GetProcAddress( DllHandle, (LPCSTR)"IntegerBackFunction" );
    pIntegerBackFunctionStd2= (int (__stdcall *)(int))GetProcAddress( DllHandle, (LPCSTR)"IntegerBackFunction2" );

    // !!!! The value on the pointers pIntegerBackFunctionStd and pIntegerBackFunctionStd2 I got here are null!!!

    In the dll it looks as following:
    --------------
    // definition
    extern "C" {
    int __declspec(dllexport) __stdcall IntegerBackFunction(void);
    int __declspec(dllexport) __stdcall IntegerBackFunction2(int param1);
    }

    // implementation/declaration
    int __declspec(dllexport) __stdcall IntegerBackFunction(void){
    return 0x3;
    }
    int __declspec(dllexport) __stdcall IntegerBackFunction2(int param1){
    printf("\nparam1=%d", param1);
    return 0x3;
    }

    What is wrong with the __stdcall-way? I have tested my application by loading another dll (a dll that is included in a commercial software) and in that case I can get values on the pointers id my functionspointer get values. So it seems that the problem is in the dll.

    I'm very thankful for any help!!

    Best regards
    Anna
    Anna K

  2. #2
    Join Date
    Mar 2002
    Location
    Izhevsk, Udmurtia, Russia
    Posts
    930
    Do you have the DllTest.def file for "DllTest.dll" project?
    With best wishes,
    Vita
    -----------------------
    Russian Software Development Network -- http://www.rsdn.ru

  3. #3
    Join Date
    Jun 2002
    Posts
    3
    No, I don't have a .def-file. I use the exporting method with __declspec(dllexport) instead.

    Anna

  4. #4
    Join Date
    Jun 2002
    Posts
    48
    Sorry, I have no solution because I can't see a reason why it should not work. But here are a few hints:
    - Type "dumpbin /exports <your-dll>" to view the functionnames (how they are really exported by your DLL)
    - GetProcAdress sets an error code which you can access with GetLastError
    - A DEF-File is only needed when you want to access the functions in VB

    Helmut

  5. #5
    Join Date
    Mar 2002
    Location
    Izhevsk, Udmurtia, Russia
    Posts
    930
    When you don't use the .def file to define the export names, then
    Code:
    extern "C" {
    1.
    __declspec(dllexport) int __cdecl IntegerBackFunction(void);
    __declspec(dllexport) int __cdecl IntegerBackFunction2(int);
    2.
    __declspec(dllexport) int __stdcall IntegerBackFunction(void);
    __declspec(dllexport) int __stdcall IntegerBackFunction2(int);
    3.
    __declspec(dllexport) int __fastcall IntegerBackFunction(void);
    __declspec(dllexport) int __fastcall IntegerBackFunction2(int);
    };
    have the following decorated names:
    Code:
    1.
    IntegerBackFunction
    IntegerBackFunction2
    2.
    _IntegerBackFunction@0
    _IntegerBackFunction2@4
    3.
    @IntegerBackFunction@0
    @IntegerBackFunction2@4
    Therefore, GetProcAddress( ..., (LPCSTR)"IntegerBackFunction" ) will be search the IntegerBackFunction name within the exports. It works for __cdecl, but not for __stdcall and other.

    You must use the GetProcAddress( ..., (LPCSTR)"_IntegerBackFunction@0" ) with correct stdcall-decorated names or the .def file, for example,
    Code:
    DESCRIPTION	'Decription of your DLL'
    EXPORTS
    	IntegerBackFunction	@1	PRIVATE
    	IntegerBackFunction2	@2	PRIVATE
    With best wishes,
    Vita
    -----------------------
    Russian Software Development Network -- http://www.rsdn.ru

  6. #6
    Join Date
    Mar 2002
    Location
    Israel
    Posts
    187
    Hm, the decoration like _FunctionName@bytes_in_arguments is a part
    of __stdcall calling convention.

    Under circumstances that generation of .def file is not a must,
    it still unclear why GetProcAddress fail to find __stdcall function.

    I would say, it seems to be a bug in GetProcAddress or in Microsoft documentation.

  7. #7
    Join Date
    Mar 2002
    Location
    Izhevsk, Udmurtia, Russia
    Posts
    930
    I would say, it seems to be a bug in GetProcAddress or in Microsoft documentation.
    The GetProcAddress() searches the specified string as a full name. It does not make the assumptions that the string may be a partial name of any decorated form.
    With best wishes,
    Vita
    -----------------------
    Russian Software Development Network -- http://www.rsdn.ru

  8. #8
    Join Date
    Apr 2002
    Location
    United Kingdom
    Posts
    310
    Use DumpBin.exe with /EXPORTS switch to see if you DLL as exported functions:

    i.e

    dumpbin /EXPORTS yourdll.dll

    This would produce a list of available export functions

    Regards

    Shaun


  9. #9
    Join Date
    Apr 1999
    Posts
    27,449
    Originally posted by Helmut Danzl

    - A DEF-File is only needed when you want to access the functions in VB

    Helmut
    No, this is not necessarily true. A DEF file is necessary if you build a DLL with the intent being that it

    a) may be loaded using LoadLibrary()

    AND

    b) The exported function name in the GetProcAddress is a "clean" function name.

    What you are thinking of is if you create an import library (LIB) file and you are writing a VC++ program that uses implicit linking to the DLL. However if your VC++ program uses LoadLibrary(), then you have to go through the correct steps of creating the DEF file if you intend on calling the function "foo" in GetProcAddress(), instead of "foo@4".

    There is a lot of confusion on this, and many VC++ programmers are fooled into thinking that a DEF file is not necessary when creating a DLL. This is the problem that the original poster is encountering. The OP is not loading the DLL implictly with an import library (as almost all VC++ programs do), they are calling LoadLibrary() with GetProcAddress(). Once you do this, you are at the mercy of the OS, and the linker or compiler does not help you out. You must specify the *exact* export name, and this is the problem that the OP is having. The exact name is not *foo*, as it would be if you used a LIB file and linked your program -- it is "foo@4" or something like that. To fix this problem a DEF file is necessary, unless the OP uses the real exported names (which are not pretty).

    Regards,

    Paul McKenzie

  10. #10
    Join Date
    Mar 2002
    Location
    Israel
    Posts
    187
    MSDN say us the follow:
    Remarks
    The GetProcAddress function is used to retrieve addresses of exported functions in DLLs.

    The spelling and case of the function name pointed to by lpProcName must be identical to that in the EXPORTS statement of the source DLL's module-definition (.DEF) file. The exported names of Win32 API functions may differ from the names you use when calling these functions in your code. This difference is hidden by macros used in the SDK header files. For more information, see Win32 Function Prototypes.
    Once more, under circumstances that generation of .def file is not a must, and identity with string from PE header export directory is not the requirement, GetProcAddress should be able to find __stdcall procedure. (This of course not concern C++, where decoration is
    significant for identification of the function).

  11. #11
    Join Date
    Jun 2002
    Posts
    3
    Thank you all for a lot of interesting reading.

    After a moment of testing all the inputs I've got here I got a new question.

    My intention was to create a dll that you may link explicitly by using LoadLibrary. I also wanted to use the stdcall-calling convention. It didn't work until I got the answer that I have to fill in the complete decorated name in the GetProcAddress-call.
    When I run the dumpbin on my dll I now see the decorated names and it all work fine.

    Then, I tried to do exact the same thing with an existing dll from a software company. They request their clients to use explicit linking and __stdcall-function calls.
    As I understood now after reading the discussions above, I should use the decorated name for the funcions. But when I run dumpbin /exports on the dll, there is no decorated names coming up. The function names coming up is proper strings with no "@" or any number of byte. Though I know that many of the functions have inparameters.
    Then I tried GetProcAddress with the undecorated names and it works(?).

    This is a confusion for me. Then I thought that maybe the dll uses a def-file anyway and searched for anything like that on my computer but couldn't find anything.

    To sum up a bit, the question is therefore
    How is the software company dll implemented? It works while making __stdcall functional calls at the same time as I don't need to put the decorated name in GetProcAddress (and dumpbin gives no decorated names)

    Thank you in advance!

    Best regards
    Anna K

  12. #12
    Join Date
    Apr 2002
    Location
    United Kingdom
    Posts
    310
    Anna,

    The DEF file is only used at compile time, I would use this as using Dumpbin.exe to retrieve decorated names is not good coding practises (but it's a great tool with lots of other operations not just /EXPORTS), the DEF file when compiles is used to alter the binary itself with the proper function names.

    Regards

    Shaun

  13. #13
    Join Date
    Apr 1999
    Posts
    27,449
    Originally posted by Anna Kagebeck
    Thank you all for a lot of interesting reading.
    ...
    Then, I tried to do exact the same thing with an existing dll from a software company. They request their clients to use explicit linking and __stdcall-function calls.
    As I understood now after reading the discussions above, I should use the decorated name for the funcions. But when I run dumpbin /exports on the dll, there is no decorated names coming up. The function names coming up is proper strings with no "@" or any number of byte. Though I know that many of the functions have inparameters.
    Then I tried GetProcAddress with the undecorated names and it works(?).
    The software company that created the DLL used a DEF file. My company does the same thing -- the DLL's are created using a DEF file, so that the exported names do not have any decoration.
    This is a confusion for me. Then I thought that maybe the dll uses a def-file anyway and searched for anything like that on my computer but couldn't find anything.
    And it's a good thing you didn't find it! Unless you have a source code license to the DLL, the company may consider the DEF file as part of their source code, meaning you could have been in a lot of legal trouble.
    To sum up a bit, the question is therefore
    How is the software company dll implemented? It works while making __stdcall functional calls at the same time as I don't need to put the decorated name in GetProcAddress (and dumpbin gives no decorated names)
    The software company's DLL was created using a DEF file in their project. So if you want to create a DLL similar to the software company, you have to add the extra step of creating a DEF file and adding it to your project that creates the DLL. Then you rebuild your DLL. Again, just using __declspec(export) and __stdcall is not enough if you want clean exported function names.

    Like I said, the confusion is that for most VC++ programmers, when they build a DLL without a DEF file, the programmers think that either

    a) the DLL is now using clean names, or

    b) GetProcAddress() does magic and can change a clean name into a decorated name.

    Neither one is true. The DLL is *not* using clean names (as you've observed), and GetProcAddress is not smart enough to change function names to find a match. Whatever function name you give GetProcAddress it had better match *exactly* what is in the export table.

    I believe that the reason for the misconception is that most of the programmers then use the DLL by adding the import library (LIB) file to their application, and the linker takes care of everything from there. I'm not sure how it does it, but a combination of the linker and import library knows that a call to "foo" is really a call to "foo@4" in the DLL.

    However, when you use LoadLibrary() and GetProcAddress() the linker is not involved, and you are not using an import library, so it does none of this "name matching" magic for you. If you want to create a DLL that is friendly to both implicit linking and GetProcAddress(), your only choice is to use a DEF file when building the original DLL, so that the exported names are clean from the start. This is exactly what my company does, and what most companies do if they intend their DLL's to be used by other languages easily and/or to provide for the most flexibility in usage.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; June 18th, 2002 at 11:17 AM.

  14. #14
    Join Date
    Mar 2002
    Location
    Israel
    Posts
    187
    Hi All,

    i believe that Microsoft tried to prevent user from changing header file
    without to change library itself.
    If it so, the name decoration help, but create another problem.
    You can put two functions with the same name, but different
    calling convention in one binary.

    May be this is the reason that GetProcAddress look for name identity.

Posting Permissions

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





Click Here to Expand Forum to Full Width

Featured