Link to home
Start Free TrialLog in
Avatar of charlesj
charlesj

asked on

problem calling a dll function

I get a NULL return value no matter if I use:

fp = GetProcAddress(hDLL,(LPCSTR)MAKELONG (nFuncNumber,0));
or
fp = GetProcAddress(hDLL, (LPCSTR)"dllfuncname");

I know that hDLL is valid, I know the function is in the dll and I know that it is exported. Why can't I get GetProcAddress() to return a good pointer to the function? And yes, I've checked the spelling and case sensitivity of the function name. I'm using MS Visual C 1.52 (16 bit)
Avatar of nietod
nietod

Is the function written in C++?  probably.  If so the problem is name mangeling.
C++ "mangles" function names by appending a "code" to the end of the name that expresses the parameters passed to the function.  This is used to impliment function overloading, where 2 or more functions have the same name and different parameters.  (Apparently the same name--C++ mangles the names so they don't).  

The function is exported with the mangeled name, so you aren't actually specifying the right name.  You can use dumpbin to verify this, you should see the function exported with a mangeled name.

To fix this problem, you can specify the mangeled name to GetProcAddress(), or--better--declared the function as "extern "C" ".  This dissables name mangeling on the function.

Let me know if you have questions.
Avatar of charlesj

ASKER

Nietod, I bet that's it (name mangling). But how can I find out what the mangled name is? Besides, the name I'm using is from right clicking on the dll file in Explorer and using QuickView to list the exported functions. Does this not give me the mangled name? I don't see how it could be giving me anything other than the mangled name. Also, why can I not get a good return value by simply using an ordinal number rather than a function name? This would bypass the mangling problem altother wouldn't it? I did observe that QuickView showed the function I want to call as exported Resident rather than exported Non-Resident. Could this be a clue? I don't have the source to the dll so I can't control mangling that way.
quick view should show the name as mangled, does it?  It may begin with a "?" and will probably be followed by a "@" and then the type names of the parameters, in order, seperated by @'s and other letters.  If you see the name exported like that, then you should be able to specify that exact name to GetProcAddress(), but that is not a good idea.  the mangeling algorithm is implimentation defined so it changes from compiler to compiler and even from version to version of the compiler, thus this mangeled name may change if you upgrade you compiler and will certainly change if you change the function's parameters.

Using the orginal should be fine.  If it is not, it suggests that there may be something else going on as well.  Maybe it would help if you posted the code that loads the DLL and obtains the procedure address.

Is the pointer returned from GetProcAddress() NULL?  If it is not NULL, then we are headed in the wrong direction, it might be a calling convection problem in that case.

>> I don't have the source to the dll so I can't control mangling that way.
Okay, that makes it sound a bit more like it could be a calling convention.  Where did this DLL come from and what do you know about the language it was written in and what parameters it expects?
Nietod,
   No, QuickView does not seem to show the name as mangled. Try using it on one of your dlls to see exactly how QuickView represents exported dll functions. Below is the code. I probably should've posted it first. That would've have made things more clear.

hDLL = LoadLibrary ("c:\\windows\\sky16v3c.dll");
if (hDLL == NULL)
{
    MessageBox (NULL, "Unable to load the dll.", "",  MB_OK);
    return NULL;
}
else
{
    fpProc = GetProcAddress (hDLL, (LPCSTR)"rdjpgfiledib");
    if (fpProc == NULL)  
    {
        FreeLibrary (hDLL);
        MessageBox (NULL, "Function not in dll.", "",  MB_OK);
        return NULL;
    }
}

   The dll is a 3rd party imaging dll. I've loaded and called my own and 3rd party dlls quite a few times. Tech support is very slow with this company though, so I thought I'd try the experts.
   As you can see I haven't gotten to the point where I try to actually call the dll so the parameters are irrelevant at this point. I could email you the dll if you think that would help you solve this. And I've cranked up the points to 100 since this is evidently a thorny prob.
Nietod,
   Do you have any thoughts regarding my efforts to use an ordinal number to get the function pointer? Doesn't it seem that name mangling can't be the issue since I get NULL even when using a number rather than a function name?
quick view will show C++ names as mangled, so that suggests that this DLL was not written in C++, thus you will need to be very concerned about calling conventions and data representation of parameters.  However, if GetProcAddress() is returning NULL, that isn't the problem at this time.

Why don't you e-mail me the DLL and I'll take a look.  My address is nietod@theshop.net.
I'm just about done for the evening, though.
use exehdr.exe to view the exports of your 16-bit DLL.  If the names shown is not exactly what you're passing into GetProcInstance, then that's your poblem.  Since you're probably using the pascal calling convention (i.e. CALLBACK, WINENTRY, WINAPI, PASCAL, etc.), case doesn't matter.
shrif and everyone,
   I used exehdr and it only told me the same thing that QuickView told me: rdjpgfiledib is an exported function. No combination of case has seemed to work. Nor can I get a pointer to the function by using a number. Using a number circumvents any problems with naming the function properly. The dll's very small. I can email it if anyone thinks they might be able to figure this out. You need MSVC 1.52, 16-bit version.
that's the way a use:

in the app who call the dll:

typedef UINT (CALLBACK* MYDLLFUNC)(char *szA, char *szB);

MYDLLFUNC MyFunc;

MyFunc = (DLLFUNC)GetProcAddress(hDLL, "MyFuncName");

UINT ret;
ret = MyFunc(szUser, szPassword);


in the dll:

extern "C" UINT PASCAL EXPORT MyFuncName(char *szUser, char *szPassword)
{
   ...

   return 1;
}

in the dll .def
EXPORTS
    MyFuncName
eric, what are you proposing as the solution?  

Do you understand the problem.  For some reason GetProcAddress() is not returning a procedure that is listed in the exports.  Nothing seems to make it work.  This is not a DLL that charles, can change, he did not write it, he only has the DLL, not the source.
erick,
   I don't think you understand the problem correctly. Read over the earlier messages or see nietod's last msg.
charlesj,

Just out of curiosity, have you checked the return value from LoadLibrary?

Email me the DLL.  I use VC++ 1.52 to call Delphi DLL's.

peter_vc@hotmail.com

peter,
    Yes, I check the return value before going on to attempt GetProcAddress ().
The test "hDLL == NULL" is not correct; you must check "hDLL > HINSTANCE_ERROR", because errors from LoadLibrary() are returned as numbers between 0 and HINSTANCE_ERROR. It is still possible that the dll is not loaded or cannot initialize, so GetProcAddress() fails (invalid hDLL). Let me know of the results.
Thanks SaGS. I waited a long time for that answer.
hey, how do I give you (SaGS) the points? I don't have any options to do so.
I can't believe I missed that!   That sill doesn't explain why the DLL doesn't load, though.
Nietod,
    Yeah, I can't believe I missed it either. But I figure I have to go figure why the dll doesn't load. I'd like to give you some points too for your efforts, but I don't know how to do that. Any ideas?
Charles
SaGS needs to submit a "dummy" answer, and then you can grade it.

No answer on the load problem, but some possibilities: It is a 32 bit DLL.  The DLL attempts to link with a DLL that is not present.  The DLL's initialization procedure (DllMain()) determines there is an error of some sort (like it can't find a file it needs) and returns an error to the OS.  
But I know for sure it's a 16-bit dll. Also, I can access it no prob with a VB app. I'm not going to worry about it until I get a chance to evaluate the return value that's coming back. They've got me busy on another task right now. Is there any way I can give you some points?
I was wondering how I missed that.  Interestingly in the VC 5 and VC 6 documentation for all the different versions of LoadLibrary() all say that NULL is returned when there is an error.  Furthermore there is no mention of HINSTANCE_ERROR in these entries nor in any other entry in the complete help--with one exception.  In any of Microsoft's code samples that call LoadLibrary(), HINSTANCE_ERROR is used in this way!!!.  i.e. this is totally undocumented, but undoubtidly correct.

>> I'm not going to worry about it until I get a chance to
>> evaluate the return value that's coming back
You might try looking at the value returned from GetLastError() as well.

>> Is there any way I can give you some points?
You can ask a "dummy" question with my name on it, although I don't feel I've done much to deserve it.  (However, I don't feel so bad about missing the obvious any longer. It wasn't obvious.)
ASKER CERTIFIED SOLUTION
Avatar of SaGS
SaGS

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
thanks SaGS
hey SaGS, if you would submit a dummy answer I'll close this question out and give you the points.
He already has and you alread have.
ok thanks nietod. adios