First, the calling convention used by the DLL function must match the function pointer definition you are using. Since it didn't match, you get the error that you've corrupted the stack.
Second, When you use GetProcAddress
the function name you use in the call to GetProcAddress
must match exactly the exported DLL function name. It has to match not only on characters, but casing also i.e. myFunction
is not the same as MyFunction
.
The exported name in your example is _myFunction@4
. which means that accessing the function using GetProcAddress
would be:
GetProcAddress(myModuleHandle, "_myFunction@4");
There is no getting around having to specify the name this way, since that is the name of the function.
So you have two options:
- Change the code as described above, that is, to use the actual name or
- Change the DLL so that the exported name is actually
myFunction
Since we covered the first option, for the second option, you have to rebuild the DLL to use a Module Definition File
(or simply known as a .DEF
file) to redefine the name.
Here is a link to what a module definition file is:
Module Definition File
So a typical .DEF file would contain this:
LIBRARY MyDLL
EXPORTS
myFunction @2
The @2
is the ordinal number
. For your purposes, it is not important what this number is since there is only one function. I chose @2
, but you can choose any number (@3
, @4
, or even @1000
if you desired). However, if there is more than 1 exported function, the ordinal numbers should be unique, i.e., you can't have two exported functions that have the same ordinal number.
If you save the above contents to a MyDll.DEF
and added it to the project that builds the DLL (not the project that will use the DLL), you will then need to rebuild the DLL. Once that's done, the DLL will now have an exported name of myFunction
without the @4
decoration and without the underscore.
(Note: As mentioned by the comment above, the extern "C"
used does not turn off the decoration that Windows uses (the additional underscore and the @x
appended to the name). All extern "C"
does is turn off the C++ name mangling. To turn off the Windows name mangling, that requires the .DEF
file.)
P.S. I use a tool called Dependency Walker
to easily determine what the exported function names are in a DLL. Since Dependency Walker is a GUI app, the output is a little friendlier than dumpbin.exe
Dependency Walker
Just to add, you mention that the DLL works flawlessly in other applications. If those other applications use import libraries
instead of using LoadLibrary
and GetProcAddress
to access the function, then those import libraries automatically handle the translation of myFunction
to _myFunction@4
.
That's why it works without issues for these types of applications. However, when you take the route of LoadLibrary
and GetProcAddress
, you are not afforded this "help" in getting the name translated, and you're basically on your own.