Solved

problem calling a dll function

Posted on 1999-01-06
27
285 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
Comment Utility
Is the function written in C++?  probably.  If so the problem is name mangeling.
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
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
Comment Utility
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
 
LVL 22

Expert Comment

by:nietod
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

Author Comment

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

Expert Comment

by:SaGS
Comment Utility
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
Comment Utility
Thanks SaGS. I waited a long time for that answer.
0
 

Author Comment

by:charlesj
Comment Utility
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
Comment Utility
I can't believe I missed that!   That sill doesn't explain why the DLL doesn't load, though.
0
 

Author Comment

by:charlesj
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
thanks SaGS
0
 

Author Comment

by:charlesj
Comment Utility
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
Comment Utility
He already has and you alread have.
0
 

Author Comment

by:charlesj
Comment Utility
ok thanks nietod. adios
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

What is C++ STL?: STL stands for Standard Template Library and is a part of standard C++ libraries. It contains many useful data structures (containers) and algorithms, which can spare you a lot of the time. Today we will look at the STL Vector. …
  Included as part of the C++ Standard Template Library (STL) is a collection of generic containers. Each of these containers serves a different purpose and has different pros and cons. It is often difficult to decide which container to use and …
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…

763 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

Need Help in Real-Time?

Connect with top rated Experts

7 Experts available now in Live!

Get 1:1 Help Now