I am trying to import a function from an unmanaged DLL into a C project by creating a .def file specifying the function I need to use. I am practicing on the WinAPI function MessageBoxA
from user32.dll
. It is an stdcall function, like the other WinAPI functions.
Here's how I create my .def file:
LIBRARY user32.dll
EXPORTS
_MessageBoxA@16
Then I create a .lib from it like this: lib /def:"C:\Path\to\def\user32.def" /
out:"C:\path\to\project\user32-mb.lib"
which successfully creates user32-mb.lib
and user32-mb.exp
. Then, in my C project, I do the following:
#pragma comment(lib, "user32-mb.lib")
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
EXTERNC __declspec(dllexport) int __stdcall MessageBoxA(void *hWnd, char *lpText, char *lpCaption, int uType);
void main(){
MessageBoxA(0, "MessageBox test", "MessageBox test", 0x00000030L);
}
However, upon linking, it gives the following error:
error LNK2019: unresolved external symbol _MessageBoxA@16 referenced in function _main
However, when I change the declaration in the .def to this:
LIBRARY user32.dll
EXPORTS
MessageBoxA
And change the function prototype in my C code to cdecl
instead of stdcall
:
EXTERNC __declspec(dllexport) int __cdecl MessageBoxA(void *hWnd, char *lpText, char *lpCaption, int uType);
The message box actually appears, but right on closing, it throws an error:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
Which indicates that calling it with cdecl
is also a bad idea since it requires stdcall
after all.
The question is, what should I change in the .def file or in my project to avoid both errors and to import and call an stdcall
function properly?
I am still not entirely sure why, but removing the _
adding the ordinal to the function name my .def
file fixed everything. My solution is:
LIBRARY USER32.dll
EXPORTS
MessageBoxA@16 @2093
Function definition:
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
typedef void *PVOID;
typedef PVOID HANDLE;
typedef HANDLE HWND;
typedef const char *LPCSTR;
typedef unsigned int UINT;
EXTERNC __declspec(dllimport)
int
__stdcall
MessageBoxA(
HWND hWnd,
LPCSTR lpText,
LPCSTR lpCaption,
UINT uType);