GetProcAddress does not find function in DLL - c++

I have a DLL and I want to call a function in it. I check the DLL using Dependency Walker and the result I got is:
void U2U_Test(void)
This is the code that I wrote, but GetProcAddress() returns NULL:
typedef void(*U2U_Test_pointer)();
void check() {
HINSTANCE hGetProcIDDLL1 = LoadLibrary(_T("my_dll.dll"));
if (hGetProcIDDLL1 == NULL)
return;
U2U_Test_pointer addr = (U2U_Test_pointer)GetProcAddress(hGetProcIDDLL1, "U2U_Test");
if (addr == NULL)
return;
return addr();
}

Depending on conventions and compiler used, the actual name exported in the DLL might not be exactly the same as the one you wrote in your source code.
This phenomenon is commonly called name decoration or name mangling.
In fact you are guaranteed to have exactly the same name only if
Your compiler conforms to C conventions (probably it does)
The function is exported in C and not C++. Use extern "C" to specify it.
The calling convention is _cdecl (specify __cdecl in function declaration)
For example, when call convention is __stdcall instead of __cdecl, which is common for many windows DLLs (they often write WINAPI or CALLBACK instead of __sstdcall), the name of the exported function is often suffixed by #n where n is the number of bytes expected on the stack for parameters.
In your case, it could be U2U_Test#0.
Indications like __declspec(dllimport) and __declspec(dllexport) tell the compiler to automatically take care of that kind of thing when DLLs are imported/linked at compile time.
IN C++, complex name decoration is used in order to support methods, function overloading, templates and other features, and each compiler invented crazy naming schemes to make sure there won't ever be any clash.
Because at DLL level, there's no template, no classes, only a list of exported symbols indexed by their name or an ID.
That's the reason why most DLLs are exported in C and why most header files declare functions coming from DLL inside a extern "C" { ... } block.

Related

Qt application crashes when using DLL, works fine if exported function doesn't declare APIENTRY

I built a DLL project in Visual Studio 2010 (by following this post). It contains only one function:
extern "C" __declspec(dllexport) void APIENTRY hello()
{
std::cout << "Hello DLL.\n" << std::endl;
}
Then I created a Qt console application to use that DLL. Its main.cpp contains this:
typedef bool (*f_void)(void);
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QLibrary lib("TestDll");
f_void hello = (f_void) lib.resolve(QString("hello").toLatin1());
hello();
return a.exec();
}
When I use APIENTRY in the DLL, the program crashes when calling hello(). It works fine if I remove APIENTRY from hello() declaration though. Why does this happen?
In addition to the mechanics of making a function call requiring matching calling conventions, which is fixed by giving the function pointer the correct type as described below, the calling convention affects name mangling.
extern "C" prevents the C++ modus operandi of including the type into the name, so that overloads of a function get unique names and can be differentiated during symbolic lookup. But it doesn't prevent mangling entirely. For example, the function in the question, void __stdcall hello(void) will be exported by __declspec(dllexport) as _hello#0, where the trailing number is the number of bytes in the argument list. This helps avoid the situation that the caller and callee disagree on the size of the arguments, which is particularly problematic in __stdcall where the callee cleans up the stack.
Nevertheless, one can disable name mangling (and the Win32 DLLs such as gdi32.dll and shell32.dll have done so). For that you need a linker definitions file:
EXPORTS
hello
; or hello = _hello#0
The linker knows about the mangling rules and will find the mangled name in the object file even if you don't provide it explicitly.
Additionally, when the exports are listed in the definition file, you no longer need __declspec(dllexport) in the code.
More information is available on MSDN.
If you call a function through a function pointer of the wrong type, you get undefined behavior. The calling convention is part of the type. Try:
typedef bool (APIENTRY *f_void)(void); // or __stdcall instead of APIENTRY
I would guess that one of your header files contains #define APIENTRY __stdcall
It's always a good idea to explicitly set the calling convention of exported functions and function pointers. If you don't, you get the currently effective default calling convention, which is a project-specific compiler option.
Pedantically, whether a function and function pointer is marked extern "C" or not is also part of the type. But on Windows, where DLLs are found, extern "C" and extern "C++" have identical effect on calling convention.

stdcall name mangling using extern c and dllexport vs module definitions (msvc++)

I was trying to export a simple test function for a dll to work with an application (fyi: mIRC) that specifies the calling convention as:
int __stdcall test_func(HWND mWnd, HWND aWnd, char *data, char *parms, BOOL show, BOOL nopause)
Now, to call this from the application, I'd be using test_func but I have noticed due to name mangling it is not as simple as I'd thought.
Through similar topics here I have come to the understanding that using extern "C" in combination with __declspec(dllexport) is an equivelant (somewhat) method of removing mangling to module definitions (.def). However, when using the extern/dllexport method my function (as an example) is always _test_func#numbers whereas the .def removed all mangling as required for use with the application i needed to export to.
Could someone please explain why this is? I'm just curious about the two methods. Thanks!
extern "C" has nothing to do with stdcall: it only declares that C++ name mangling (aka type-safe linkage; inclusion of type information in symbol name) is disable. You need to use it independent of whether you use C calling convention or stdcall calling convention.
In stdcall calling convention, the callee removes the parameters from the stack. To make that safe, the exported name contains the number of bytes that the callee will remove from the stack.
If the application you are exporting to requires that no #number suffix is added to the name, it probably means that it expects C calling convention. So you should stop declaring the function as __stdcall. When you the declare it as declspec(dllexport), you should get an undecorated name in the DLL.
In the DEF file, you can call the function whatever you want; no additional checking is performed.
dllexport/import are designed to be loaded back by themselves, not an old C library using GetProcAddress. The mangling you have seen is what all Microsoft compilers have done for a long time for __stdcall functions. Most likely, your target either expects a __cdecl function, not __stdcall, but if not, you will need to use a .def file to specifically un-mangle the name.

extern "C" not working as expected

I am trying to hook a Win32 API function. I am making a DLL from which I want to export the function, but I am already failing at the basics. My declaration is as follows:
extern "C" __declspec(dllexport) int WINAPI fnTest(void);
but the exported function name is not "fnTest" - as I would expect - but is "_fnTest#0". I can only make it work when declaring the functions calling convention to __cdecl, which results to an exported name of "fnTest", but since the Win32 calling conection is WINAPI/__stdcall this is not an option.
I am using VS2010. Thanks in advance.
That mangling is part of the __stdcall convention. As the called function has the responsibility to remove the parameters from the stack on return, and removing the wrong amount of data from the stack has disastrous consequences, the number of bytes the parameters take is simply appended to the function name after "#" to let the linker catch potential conflicting definition errors.
Could you explain exactly, how does this pose a problem?
You should use module definition file (.def) instead of __declspec(dllexport).
Just use the following .def file:
EXPORTS
fnTest
If you want to do this you will have to export the functions by ordinal rather than by name using a .DEF file.
stdcall provides a decoration that describes the length of the parameters, in this case #0 since you have no parameters. If you had one parameter it would be #4, and so on.

better understanding of extern "C" functions

I am just trying to further understand extern C functions.
According to my knowledge, an extern C function is always a function you are trying call from an application that has already been compiled. Either a executable, static or dynamic library.
extern "C"
{
HRESULT CreateDevice();
typedef HRESULT (*CREATEDEVICE)();
HRESULT ReleaseDevice();
typedef HRESULT (*RELEASEDEVICE)();
}
So my question is...
Is my understanding correct ??
Does it always have to be a C function pointer ??'
Why must you use a typedef for each function ??
I presume that when you use the GetProcAddress(). You are allocating memory on that particulars applications HEAP and not the one you are calling it from. Therefore you must release it from that heap as well ??
extern "C" has 2 implications. First, it declares that the symbolic names of the functions are not "name mangled" to support C++. Second, it tells the compiler that the function is called using the C calling convention rather than the PASCAL calling convention. The difference has to do with when the return address is pushed on the stack. Using the wrong calling convention will crash your app.
This declaration is for the compiler, not the linker. So the extern C function could exist in your own modules or in a binary library: the source of actual bytes for the function implementation are resolved by the linker. If the function signature is declared as a regular C++ function and not extern C, the compiler will mangle the symbolic name to encode type information from the function signature. This will make it incompatible with object code generated by other C++ compilers. Therefore creating an extern C function allows you to share code between compilers in binary form. Note that you can't expose member functions this way, only old-style C functions.
It doesn't have to be a function pointer. You can specify the function declaration normally and prefix it with extern "C", as shown in some Microsoft examples.
If you use GetProcAddress() you are not allocating any memory. You simply get the memory address of the function inside the DLL that has already been loaded into memory (with LoadLibrary(), presumably).
Even when using function pointers (such as those returned by GetProcAddress) you don't have to use typedef, it's just that the code looks pretty ugly without it. It's always hard to figure out what to write as well. I think it would be something like:
void (*pReleaseDevice)() = (void (__cdecl *)(void))GetProcAddress(hInstance, "ReleaseDevice");
extern "C" {} is a C++ convention to declare that the enclosed functions are C functions -- not C++ functions. C++ has a slightly different naming convention which conflicts with C. If you have a library written in C and want to use it in a C++ program, you have to use extern "C" {} to let the compiler know these are C functions. If the library was written in C++ I believe the extern "C" {} will cause an error.
Note that extern has multiple meanings -- this specific case is a C++ convention and is unrelated to different uses of extern. For example,
extern int count;
has a completely different meaning than extern "C" {}.
The typedef is separate from the extern "C" {} issue. typedefs let you create aliases for common types that make more sense. For example, declaring structs is often a verbose process. I can use a typedef to shorten it:
struct mystruct {int a; int b};
typedef struct mystruct returncode;
// I can now declare a variable as type 'returncode'
returncode a;
Thus, in your example the HRESULT is really an alias for (*CREATEDEVICE)() although I believe you have to put it before the function (and not after).
One important aspect of specifying extern "C" linkage is that the function names do not get mangled, which is the default for C++ names.
In order for your library's functions to be able to be loaded using GetProcAddress, you need to either add the function to the .def file, use __declspec(dllexport) or use extern "C".
To answer, in order:
extern "C" functions are used for interop with C from C++. Using them has the consequence that C code can call the function. As the windows API is a C API all functions are extern "C" to ensure that C and C++ code can make use of the API.
In order for c++ programs to interoperate with other languages, including C, as a convention , functions are exported using extern "C". Which is why a lot of dll code does this. It is not a technical requirement however.
So no, it does NOT have to be a C function pointer.
You don't have to use typedef's either.
The example code provided is from a header file that is publishing the exports of a DLL twice - Once as the set of extern "C" methods that are exported so that the dll can be statically linked. the other as a set of function pointer types, so that the dll can be dynamically loaded, and the function pointer types used with GetProcAddress.

Overloaded functions in C++ DLL def file

I'm writing a C/C++ DLL and want to export certain functions which I've done before using a .def file like this
LIBRARY "MyLib"
EXPORTS
Foo
Bar
with the code defined as this, for example:
int Foo(int a);
void Bar(int foo);
However, what if I want to declare an overloaded method of Foo() like:
int Foo(int a, int b);
As the def file only has the function name and not the full prototype I can't see how it would handle the overloaded functions. Do you just use the one entry and then specify which overloaded version you want when passing in the properly prototyped function pointer to LoadLibrary() ?
Edit: To be clear, this is on Windows using Visual Studio 2005
Edit: Marked the non-def (__declspec) method as the answer...I know this doesn't actually solve the problem using def files as I wanted, but it seems that there is likely no (official) solution using def files. Will leave the question open, however, in case someone knows something we don't have overloaded functions and def files.
Function overloading is a C++ feature that relies on name mangling (the cryptic function names in the linker error messages).
By writing the mangled names into the def file, I can get my test project to link and run:
LIBRARY "TestDLL"
EXPORTS
?Foo##YAXH#Z
?Foo##YAXHH#Z
seems to work for
void Foo( int x );
void Foo( int x, int y );
So copy the C++ function names from the error message and write them into your def file. However, the real question is: Why do you want to use a def file and not go with __declspec(dllexport) ?
The mangled names are non-portable, I tested with VC++ 2008.
In the code itself, mark the functions you want to export using __declspec(dllexport). For example:
#define DllExport __declspec(dllexport)
int DllExport Foo( int a ) {
// implementation
}
int DllExport Foo( int a, int b ) {
// implementation
}
If you do this, you do not need to list the functions in the .def file.
Alternatively, you may be able to use a default parameter value, like:
int Foo( int a, int b = -1 )
This assumes that there exists a value for b that you can use to indicate that it is unused. If -1 is a legal value for b, or if there isn't or shouldn't be a default, this won't work.
Edit (Adam Haile): Corrected to use __declspec as __dllspec was not correct so I could mark this as the official answer...it was close enough.
Edit (Graeme): Oops - thanks for correcting my typo!
I had a similar issue so I wanted to post on this as well.
Usually using
extern "C" __declspec(dllexport) void Foo();
to export a function name is fine.
It will usually export the name
unmangled without the need for a
.def file. There are, however, some
exceptions like __stdcall functions
and overloaded function names.
If you declare a function to use the
__stdcall convention (as is done for many API functions) then
extern "C" __declspec(dllexport) void __stdcall Foo();
will export a mangled name like
_Foo#4. In this case you may need to explicitly map the exported name
to an internal mangled name.
A. How to export an unmangled name. In a .def file add
----
EXPORTS
; Explicit exports can go here
Foo
-----
This will try to find a "best match" for an internal function Foo and export it. In the case above where there is only
one foo this will create the mapping
Foo = _Foo#4
as can be see via dumpbin /EXPORTS
If you have overloaded a function name then you may need to explicitly say which function you want in the .def file
by specifying a mangled name using the entryname[=internalname] syntax. e.g.
----
EXPORTS
; Explicit exports can go here
Foo=_Foo#4
-----
B. An alternative to .def files is that you can export names "in place" using a #pragma.
#pragma comment(linker, "/export:Foo=_Foo#4")
C. A third alternative is to declare just one version of Foo as extern "C" to be exported unmangled. See here for details.
There is no official way of doing what you want, because the dll interface is a C api.
The compiler itself uses mangled names as a workaround, so you should use name mangling when you don't want to change too much in your code.
There isn't a language or version agnostic way of exporting an overloaded function since the mangling convention can change with each release of the compiler.
This is one reason why most WinXX functions have funny names like *Ex or *2.
Systax for EXPORTS definition is:
entryname[=internalname] [#ordinal [NONAME]] [PRIVATE] [DATA]
entryname is the function or variable name that you want to export. This is required. If the name you export is different from the name in the DLL, specify the export's name in the DLL with internalname.
For example, if your DLL exports a function, func1() and you want it to be used as func2(), you would specify:
EXPORTS
func2=func1
Just see the mangled names (using Dependency walker) and specify your own functions name.
Source: http://msdn.microsoft.com/en-us/library/hyx1zcd3(v=vs.71).aspx
Edit: This works for dynamic DLLs, where we need to use GetProcAddress() to explicitly fetch a functions in Dll.