Link to home
Start Free TrialLog in
Avatar of Nitemare
Nitemare

asked on

Accessing function in a DLL via LoadLibrary and GetProcAddress

So far I used to load dlls at load-time therefore compiled my programs with .lib file that linker made when building a dll. Now I've come to a situation when I would like to execute a function in a dll via LoadLibrary. Well it works to the point when I issue a command GetProcAddess which never gets a lock onto function that I know is in a dll (I made my dll).
When I tried to see what's in the Export table of a dll through quick view in Win95 I saw nothing. The export table showed up only if I quick view a dll in WinNT. Why????
The other thing is that the name of a function looks like this : 0000 ?Func1@@YAXXZ or something. Strange that ordinal number began with 0 instead of 1. My function is simply void Func1 (void) and nothing else. I exported it via __declspec(dllexport). Otherwise if I include .lib file that was generated with dll to my .exe I can successfuly call Func1.

What am I doing wrong????
ASKER CERTIFIED SOLUTION
Avatar of nietod
nietod

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of jhance
jhance

I assume that you are using C++.  If so, then the problem is what is called name "mangling" or decoration by the compiler.  In order to make sure that there are no name collisions between the different functions in a class, the compiler does some things to the names of each function to ensure that it is unique in all cases.  This is normally transparent to the user of a program or static library as you don't ever deal with the names of the functions except at compile time, and they are not decorated at that point.  Using a DLL, however, required that you know the name of the function as it appears in the DLL itself.  There are three ways around this problem:

1) Use ORDINALS to select the function instead of the name.
2) Look in the symbol table and get the decorated name of the function (a real pain as the name can change)
3) Use extern "C" before your function declarations.  This forces the compiler to use "C" name conventions for this function instead of decorated C++ names.

I tend to use #3 for exported functions.
The problem is C++'s name decoration.  This is a system by which C++ adds suff to the end of the name (the stuff you saw) in order to "descrbe" the parameters to the function.  By doing this, overloaded function which _appear_ to have the same name in C++ are actually generated with unique names.  You can use GetProcAddress() witht he appropriate decorated name (just tack on all that stuff you saw), but that is not recmended.  The name decoration system is not standardized, so differnet compilers or even different versions of the same compiler will generate different decorations.  Thus this might require you to change the name from time-to-time.  So instead, if you dissable the decoration process, you can load the procedure with the name you gave it.  If you declare the procedure as extern "C", it will not be decorated.
One more thing, if you use extern "C", you have dissabled the overloading scheme on that particular function.  You can still overload other functions and you can even overload other functions with the same name.  However, you cannot overload two functions that have the same name and are both declated extern "C".
Avatar of Nitemare

ASKER

OK let's assume this example:

This goes for a dll file

#include <stdio.h>

void __declspec(dllexport) Func1(void)

void Func1(void)
{
   printf ("Func1 output\n");
}

Now when I call a function in my exe I do next

typedef void (*MY)(void)

    MY myroc;

LoadLibrary and so on....

    myproc = (MY) GetProcAddress(hinst, "Func1");
And this is where all stop

I could call a function then like : (myproc)();

declaring a Func1 as extern is not important since a function gets called via pointer. Furthermore this is like an example from a book and it doesn't work!!!

The only thing I didn't check at the moment of writing this comment is if I should change the exact function name specified in GetProcAddress and how to disable name mangling or whatever that is so that dll would reflect the function names like if you look say User32.dll and all you see are "clean" function names.

Any suggestions...
Something tells me I should stick to straight C not C++ when writing dlls.
Calling a function with ordinals is out of question since my program should run on NT as well as on 95/98 and ordinal assignment is different on those two.... am I wrong here too
>> Something tells me I should stick to straight C not C++ when writing dlls
not true at all.  But if you want to load a procedure by name (GetProcAddress()) then you will want to dissable name mangeling.

As I said before.  You either need to specify the mangled name to GetProcAddress().  That is, the name you found when you looked at the DLL's exports. OR (better yet) dissable name mangeling by declaring the function as extern "C"

Try

extern "C" void __declspec(dllexport) Func1(void)
{
     printf ("Func1 output\n");
}
>> Calling a function with ordinals is out of question since my program
>> should run on NT as well as on 95/98 and ordinal assignment is different
>> on those two.... am I wrong here too
The ordinals of someof the OS DLLs may be different.   (I never heard that before , however).  But that doesn't have any effect on a DLL you write.  When you create the DLL, you specify (or at least determine) the ordinals.  That won't change unless the DLL is altered.  It can be copied to a computer using either OS and the ordinals will stay the same.  (Basically the DLL has a list of exported functions that is numbered starting fom 0.  The ordinal of a function is its position in the list.)  

So you can load by ordinal, but I wouldn't recomend it unless you are very sure that the DLL won't need future modifications.  Modifications that add or remove exported procedures makes loading by ordinal a little more risky, or at least a little more difficult.  (It is however faster and generates smaller code.)
nietod yes I tried that and it works as it works calling a func with mangled name. The portion about different ordinals is explained in Programming Windows NT 4 from SAMS Publishing. I figured that tricky extern declaration now when it was brought to me. Good work. Thx.
Jhance thx to you too but I can only give points to one. Next time.