功能和动态加载dll导出的功能

时间:2020-06-03 16:06:56

标签: c++ function templates

在进行其他讨论(Discussion 1Discussion 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失败。

我在哪里错了?

0 个答案:

没有答案