c++ - DLL call with __stdcall & GetProcAddress() in VS2013 -
i'm trying call function own dll, depending on calling convention in dll project either can't find procaddress or stack getting corrupted. works 3rd party dlls not change in loading code if there no major problem there. minimal example:
#include <windows.h> #include <cstdlib> #include <iostream> typedef long (__stdcall* tmyfunction)(int); int main(int argc, char* argv[]){ hinstance m_dllhandle = loadlibrary("mydll.dll"); if (m_dllhandle != null){ tmyfunction function = (tmyfunction)getprocaddress(m_dllhandle, "myfunction"); if (function != null){ long value = function(1); std::cout << value << std::endl; }else{ std::cout << "getprocaddress() failed" << std::endl; } freelibrary(m_dllhandle); m_dllhandle = null; }else{ std::cout << "loadlibrary() failed" << std::endl; } system("pause"); return exit_success; } in dll:
extern "c" __declspec(dllexport) long __stdcall myfunction(int a){ return 10; } result: getprocaddress() fails
dumpbin /exports -> _myfunction@4 = _myfunction@4
extern "c" __declspec(dllexport) long __cdecl myfunction(int a){ return 10; } result: "run-time check failure #0 - value of esp not saved across function call. result of calling function declared 1 calling convention function pointer declared different calling convention." (because use __stdcall in loading code , __cdecl in dll).
dumpbin /exports -> _myfunction = _myfunction
in 3rd party dlls, can see, "dumpbin /exports" shows myfunction (no underscores, no @4) can accomplish same , still able load above defined type (typedef long (__stdcall* tmyfunction)(int);)? compiler "visual studio 2013".
first, calling convention used dll function must match function pointer definition using. since didn't match, error you've corrupted stack.
second, when use getprocaddress function name use in call getprocaddress must match exactly exported dll function name. has match not on characters, casing i.e. myfunction not same myfunction.
the exported name in example _myfunction@4. means accessing function using getprocaddress be:
getprocaddress(mymodulehandle, "_myfunction@4"); there no getting around having specify name way, since is name of function.
so have 2 options:
- change code described above, is, use actual name or
- change dll exported name
myfunction
since covered first option, second option, have rebuild dll use module definition file (or known .def file) redefine name.
here link module definition file is:
so typical .def file contain this:
library mydll exports myfunction @2 the @2 ordinal number. purposes, not important number since there 1 function. chose @2, can choose number (@3, @4, or @1000 if desired). however, if there more 1 exported function, ordinal numbers should unique, i.e., can't have 2 exported functions have same ordinal number.
if save above contents mydll.def , added project builds dll (not project use dll), need rebuild dll. once that's done, dll have exported name of myfunction without @4 decoration , without underscore.
(note: mentioned comment above, extern "c" used not turn off decoration windows uses (the additional underscore , @x appended name). extern "c" turn off c++ name mangling. turn off windows name mangling, requires .def file.)
p.s. use tool called dependency walker determine exported function names in dll. since dependency walker gui app, output little friendlier dumpbin.exe
just add, mention dll works flawlessly in other applications. if other applications use import libraries instead of using loadlibrary , getprocaddress access function, import libraries automatically handle translation of myfunction _myfunction@4.
that's why works without issues these types of applications. however, when take route of loadlibrary , getprocaddress, not afforded "help" in getting name translated, , you're on own.
Comments
Post a Comment