just for the fun of it, a c++14 version
PHP Code:
#include <string>
#include <memory>
#include <map>
#include <system_error>
template <typename F, typename... ArgTypes>
auto DynCallT(LPCTSTR libName, LPCSTR funcName, ArgTypes... args)
{
using tstring = std::basic_string<TCHAR, std::char_traits<TCHAR>, std::allocator<TCHAR>>;
using lib_ptr = std::shared_ptr<std::remove_pointer_t<const HMODULE>>;
using lib_map = std::map<const tstring, lib_ptr>;
static lib_map libMap;
HMODULE h = nullptr;
const auto &l = libMap.find(libName);
if(l != libMap.end())
h = l->second.get();
else if((h = ::LoadLibrary(libName)) != nullptr)
libMap[libName] = lib_ptr(h, ::FreeLibrary);
else
throw std::system_error(std::make_error_code(std::errc::invalid_argument));
F f = reinterpret_cast<F>(::GetProcAddress(h, funcName));
if(!f)
throw std::system_error(std::make_error_code(std::errc::function_not_supported));
return f(args...);
}
usage:
PHP Code:
// using 'decltype' when you have a prototype
auto r = DynCallT<decltype(&MessageBoxA)>(_T("user32"), "MessageBoxA", nullptr, "123", "321", 0);
// or using func decl as template arg
auto tc1 = DynCallT<DWORD(WINAPI*)()>(_T("kernel32"), "GetTickCount");
// using "i dont give a shit" decl :)
auto tc2 = DynCallT<void*(WINAPI*)(...)>(_T("kernel32"), "GetTickCount", 1, "asd");
void WINAPI blub(DWORD);
DynCallT<decltype(&blub)>(_T("kernel32"), "Sleep", 0);