Click to See Complete Forum and Search --> : GetProcAddress() Can't See Exported Function Names?
Jason Teagle
April 15th, 1999, 07:20 AM
I recently posted a query on exporting functions from a DLL. I am posting again as I have slightly more information, but still need help.
My problem is that if I declare, in my DLL:
---
extern "C"
{
void _declspec(dllexport) _stdcall DLL_HelloWorld(void);
}
---
and in my test program, which wants to use the DLL:
---
void (FAR *lpfnHelloWorld)(void);
lpfnHelloWorld =
(void (FAR *)(void) )::GetProcAddress(hInstDLL,"DLL_HelloWorld");
---
lpfnHelloWorld always ends up as NULL.
Someone suggested that I use dumpbin to see what was being exported; sure enough, I see:
---
ordinal XXXXX name
1 0 _DLL_HelloWorld@0
---
Presumably this IS the unmangled version, as the gibberish on the end of the name gets worse if I don't use extern "C".
So, if the function is being exported OK, why can't GetProcAddress() find it by name?
I say 'by name' because I tried:
---
void (FAR *lpfnHelloWorld)(void);
lpfnHelloWorld =
(void (FAR *)(void) )::GetProcAddress(hInstDLL,(LPCSTR)(DWORD)1);
---
and Bingo! It worked.
Now, why can't the function find the name when it CAN find the ordinal? I don't want to use ordinals as they don't mean anything to anyone reading the code, and might change.
Any ideas?
Paul McKenzie
April 15th, 1999, 07:54 AM
Did you use a .DEF file for the DLL?
Jason Teagle
April 15th, 1999, 07:59 AM
VC++ created one for me, and I have not touched it. I assume you ask because of the EXPORTS section; I understood that using _declspec(dllexport) did the same job as listing functions in the DEF file?
April 15th, 1999, 08:00 AM
I think that the mangling is caused by the __stdcall directive.
Jason Teagle
April 15th, 1999, 08:34 AM
You are absolutely right. I thought this was the 32-bit version of FAR PASCAL, which I used to use for 16-bit DLLs (which worked, I might add). On looking at the help again, it seems I got a bit cross-eyed - it is WINAPI I should be using instead.
However, when I used WINAPI, it was mangled in the same way! (without this extra modifier, it worked properly).
Now I am confused. How come it used to work in 16-bit, but doesn't in 32-bit?
Also, I want this DLL to be usable from VB as well - I understood that I HAD to use FAR PASCAL (arguments placed on stack in reverse order) to use it with VB - is this wrong? Will VB be able to see the functions and use them if they are declared without the extra modifier? I can try that much, I know; I'm just surprised that it doesn't seem to work with the modifier now.
Another question while I'm here: When you use API or MFC functions / methods, they are included from the appropriate H file (say, CWnd::SetWindowPos() ), and the linked LIB file helps to show the compiler that the function will exist in the DLL at run time.
How can I create the LIB file that I link at compile time so that I can simply include my header file and call the function as if it was defined in my own project? Is this what the LIB file that is created when you compile the DLL does?
Paul McKenzie
April 15th, 1999, 09:34 AM
The _declspec(dllexport) *only* does that -- exports the function. If you want to use a "mangle-free" name, you would use a .DEF file. This is the only way that I found that takes the name-mangling off completely. BTW, I think the name that you saw with the extra decoration *is* the name of the function.
I've always used .DEF files, especially since the rules of exported function naming changed somewhat between 16 and 32-bit DLL's. Since using DEF files, I have never had a problem with any of my exported function names with VC++ or VB (or any language that I've used my DLL's with).
Regards,
Paul McKenzie
Paul McKenzie
April 15th, 1999, 09:41 AM
To add to my previous message...
Keep the _stdcall directive. 32-bit VB needs this to work properly since that's the way it expects to see the arguments.
Regards,
Paul McKenzie
Jason Teagle
April 15th, 1999, 09:43 AM
This definitely makes sense, I think I will change to that method. Do you use WINAPI (= FAR PASCAL) for your functions, though?
The changes between 16-bit and 32-bit accounts for why code suddenly won't work when ported. Thanks, Microsoft, for detailing that in a way that human beings can find.
One final question: How should the function be listed under EXPORTS? Can you give me an example of a DEF file with EXPORTS so that I can see? I only started using _export in 16-bit because I didn't understand what I was supposed to write in the DEF file!
Thanks for your help.
Paul McKenzie
April 15th, 1999, 09:50 AM
The .LIB file (more officially called the import library) can be created if you successfully build the DLL yourself (by default, I think that VC++ places it in the /DEBUG or /RELEASE subdirectory of your project), or you can use LIB.EXE to create an import library from an existing DLL.
The import library resolves any external function calls that it can't find in your object code.
Regards,
Paul McKenzie
Jason Teagle
April 15th, 1999, 10:12 AM
OK - I have kept the _stdcall required for VB, moved the exporting to the DEF file (I must have been a bit green when I first looked at it - I got it right first time this time round), and compiled; my test program works great with the long-winded method I have used in this example. Wonderful!
Now I am trying to use the easy method where I include the header file, link with the LIB file and just call the function. This has caused a slight naming problem.
1. I assume that I can just include exactly the same header file that I compiled the DLL with, is this correct? (Or at least, a header file with just the exported function prototypes in.)
2. When it tried to link, it found the library but said:
UseDLLView.obj : error LNK2001: unresolved external symbol _DLL_HelloWorld
Debug/UseDLL.exe : fatal error LNK1120: 1 unresolved externals
when I tried to make this call:
DLL_HelloWorld();
It obviously recognised the function name from the header file, but couldn't seem to find it in the LIB; I guess this is why when I tried this method of accessing DLL functions before I gave up - but then I didn't have access to discussion areas like this.
Any idea as to what I've done wrong?
Thanks.
Paul McKenzie
April 15th, 1999, 10:18 AM
Try this piece of magic (works in 16 and 32-bit DLL definitions):
This is in FUNCPFX.H:
-------------------------------------------
#if defined(WIN32) || defined(_WIN32)
#if defined (DLL_BUILD)
#define FUNCPREFIX __declspec(dllexport) __stdcall
#else
#define FUNCPREFIX __stdcall
#endif
#else
#if defined(DLL_BUILD)
#define FUNCPREFIX __export FAR PASCAL
#else
#define FUNCPREFIX FAR PASCAL
#endif
#endif
------------------------------------------------
This is in MYAPI.H
#include <funcpfx.h>
// Exportable MyProc(int) function.
extern "C" BOOL FUNCPREFIX MyProc(int);
------------------------------------------
The Following EXPORTS section should be added to the DEF file (don't erase the one that VC created):
EXPORTS
; This exports the MyProc with an ordinal of 10
MyProc @10
-----------------------------------------------
Note:
If you're building the DLL, define the preprocessor symbol DLL_BUILD on the command line (or IDE settings). The beauty of the funcpfx.h is that you can use the same headers for 16 or 32-bit builds, and the headers are portable between the build of the DLL and using the DLL in a project.
Regards,
Paul McKenzie
Paul McKenzie
April 15th, 1999, 10:22 AM
See my other post concerning the souped up header file that I use. This may clear up the problem.
Regards,
Paul Mckenzie
Paul McKenzie
April 15th, 1999, 10:27 AM
Oh, almost forgot...
In the C or C++ implementation for MyProc():
#include <myapi.h>
...
BOOL FUNCPREFIX MyProc(int)
{
...
}
Regards,
Paul McKenzie
Jason Teagle
April 16th, 1999, 02:07 AM
Paul, I wish to thank you for your efforts. I have now got the DLL and test program to compile and run successfully using both the long-winded GetProcAddress() method and the easier link-to-lib-and-call-normally method. I don't know why the link to LIB didn't work the first time, but it doesn't matter, it's all working perfectly.
Thankyou.
Paul McKenzie
April 16th, 1999, 03:13 AM
Great! Did you use the header with the #defines that I posted or did you go it alone?
Paul McKenzie
Jason Teagle
April 16th, 1999, 03:18 AM
I used your headers, thankyou. As it is still quite likely that I will be writing 16-bit code now and then, it seemed an excellent idea.
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.