在进行其他讨论(Discussion 1和Discussion 2)之后,我编写了一些代码,以使用基于模板的辅助函数来动态加载从dll导出的加载函数。
它工作正常,但是即使从dll导出的函数是cdecl函数也是如此。如果他们有不同的通话习惯,我会感到麻烦,我正在寻找一个好的建议。
以下是我的一些代码:
template <typename Ret, typename... Args >
Ret ExecuteIt(LPCSTR funName, Args... Pack)
{
std::map<LPCSTR, CGenericHolder*>::iterator it;
it = m_functionsMap.find(funName);
if (it != m_functionsMap.end())
{
CGenericHolder* tmpObj = it->second;
if (tmpObj->IsValid())
{
CVarFuncHolder<Ret(Args...)>* tmpObjF = dynamic_cast<CVarFuncHolder<Ret(Args...)>*>(tmpObj);
if (tmpObjF)
return tmpObjF->ExecuteIt()(Pack...);
else
throw std::bad_cast("Object doesn't match the function");
}
}
throw std::bad_function_call("Function not exists");
};
template <typename T>
bool MapMemberFunction(LPCSTR funName, int ordinal = -1)
{
CVarFuncHolder<T>* newFun = new CVarFuncHolder<T>();
bool rv = true;
try
{
newFun->Assign(funName, loadDllFunc<T>(funName,ordinal));
m_functionsMap[funName] = newFun;
}
catch (const std::invalid_argument& e)
{
#ifdef _DEBUG
OutputDebugStringA(e.what());
#endif
delete newFun;
rv = false;
}
catch (...)
{
throw;
}
return rv;
};
template <typename T>
std::function<T> loadDllFunc(LPCSTR funcName, int ordinal)
{
// Load DLL.
// Check if DLL is loaded.
if (!m_dllHinst)
throw std::invalid_argument("Dll not loaded");
// Locate function in DLL.
FARPROC lpfnGetProcessID = ::GetProcAddress(m_dllHinst, (ordinal >= 0) ? MAKEINTRESOURCEA(ordinal) : funcName);
// Check if function was located.
if (!lpfnGetProcessID)
throw std::invalid_argument("Function call not found");
// Create function object from function pointer.
auto f = CastFromFPtrToFunction<T>(lpfnGetProcessID);
return f;
}
template<typename Signature>
std::function<Signature> CastFromFPtrToFunction(FARPROC f)
{
return std::function<Signature>(reinterpret_cast<Signature*>(f));
}
现在,
我以这种方式映射想要的功能
if (!MapMemberFunction<long (long, unsigned char, unsigned char)>("Func name"))
return false;
我以这种方式使用该功能:
auto rv = ExecuteIt<long>("Func name", par1, par2, par3);
如果该函数是使用cdecl调用约定编写的,则一切正常,但是如果该函数具有不同的调用约定,则应用程序将崩溃。
我试图以其他方式映射功能
MapMemberFunction<long APIENTRY (long, unsigned char, unsigned char)>("Func name"));
但是在后者中,我调用Excute方法有问题,因为dynamic_cast失败。
我在哪里错了?