Solved

problem calling a dll function

Posted on 1999-01-06
27
295 Views
Last Modified: 2008-02-20
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)
0
Comment
Question by:charlesj
  • 13
  • 9
  • 2
  • +3
27 Comments
 
LVL 22

Expert Comment

by:nietod
ID: 1181667
Is the function written in C++?  probably.  If so the problem is name mangeling.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1181668
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.
0
 

Author Comment

by:charlesj
ID: 1181669
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.
0
Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
LVL 22

Expert Comment

by:nietod
ID: 1181670
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?
0
 

Author Comment

by:charlesj
ID: 1181671
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.
0
 

Author Comment

by:charlesj
ID: 1181672
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?
0
 
LVL 22

Expert Comment

by:nietod
ID: 1181673
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.
0
 
LVL 1

Expert Comment

by:shrif
ID: 1181674
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.
0
 

Author Comment

by:charlesj
ID: 1181675
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.
0
 

Expert Comment

by:erick1217
ID: 1181676
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
0
 
LVL 22

Expert Comment

by:nietod
ID: 1181677
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.
0
 

Author Comment

by:charlesj
ID: 1181678
erick,
   I don't think you understand the problem correctly. Read over the earlier messages or see nietod's last msg.
0
 
LVL 1

Expert Comment

by:peter_vc
ID: 1181679
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

0
 

Author Comment

by:charlesj
ID: 1181680
peter,
    Yes, I check the return value before going on to attempt GetProcAddress ().
0
 
LVL 4

Expert Comment

by:SaGS
ID: 1181681
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.
0
 

Author Comment

by:charlesj
ID: 1181682
Thanks SaGS. I waited a long time for that answer.
0
 

Author Comment

by:charlesj
ID: 1181683
hey, how do I give you (SaGS) the points? I don't have any options to do so.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1181684
I can't believe I missed that!   That sill doesn't explain why the DLL doesn't load, though.
0
 

Author Comment

by:charlesj
ID: 1181685
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
0
 
LVL 22

Expert Comment

by:nietod
ID: 1181686
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.  
0
 

Author Comment

by:charlesj
ID: 1181687
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?
0
 
LVL 22

Expert Comment

by:nietod
ID: 1181688
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.)
0
 
LVL 4

Accepted Solution

by:
SaGS earned 100 total points
ID: 1181689
See my last comment.

Other things:
If you can load the library from VB but not C, it is possible that it needs some VB run-times or the run-time environment created by VB apps (the memory management routines for VB-like strings, for example, should be provided by the main app). I know you cannot use *.VBX controls form C/C++ unless you create an app that especially enbles the necessary support (in AppWizard) - and there may be problems even in this case. Don't know about this particular dll; are you sure it can be called from "plain" C/C++? Other thing (less probable): check if it does not need additional dlls that cannot be found when you execute yout app, but can be found if you execute other apps (dlls are searched, among other places, in the directory containing the calling app).

If you need the error codes returned by LoadLibrary(), here is what I have (for 16-bit apps):

0   Out of memory, executable file was corrupt, or relocations were invalid.
2   File was not found.
3   Path was not found.
5   Attempt was made to dynamically link to a task, or there was a sharing or network-protection error.
6   Library required separate data segments for each task.
8   There was insufficient memory to start the application.
10  Windows version was incorrect.
11  Executable file was invalid. Either it was not a Windows application or there was an error in the .EXE image.
12  Application was designed for a different operating system.
13  Application was designed for MS-DOS 4.0.
14  Type of executable file was unknown.
15  Attempt was made to load a real-mode application (developed for an earlier version of Windows).
16  Attempt was made to load a second instance of an executable file containing multiple data segments that were not marked read-only.
19  Attempt was made to load a compressed executable file. The file must be decompressed before it can be loaded.
20  Dynamic-link library (DLL) file was invalid. One of the DLLs required to run this application was corrupt.
21  Application requires Microsoft Windows 32-bit extensions.

0
 

Author Comment

by:charlesj
ID: 1181690
thanks SaGS
0
 

Author Comment

by:charlesj
ID: 1181691
hey SaGS, if you would submit a dummy answer I'll close this question out and give you the points.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1181692
He already has and you alread have.
0
 

Author Comment

by:charlesj
ID: 1181693
ok thanks nietod. adios
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Focus not getting shifted out of  editbox 2 66
Getting IP address 8 89
find Speed using GPS latitude & longitude 4 48
boost::uuid crashes 17 13
Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

821 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question