簡體   English   中英

有沒有一種方法可以在容器中存儲不同的函數指針類型

[英]Is there a way to store different function pointer types in a container

在下面的代碼中,我試圖將函數指針存儲在向量中,但是每個函數指針都有一個不同的簽名。

以下代碼的想法是,當我加載DLL時,我僅使用循環將DLL中的所有函數加載到向量中。 然后,當我想調用一個函數時,我只是按名稱或索引來調用它,並傳遞可變數量的參數。 但是我真的很想以與加載它們相同的方式調用這些函數:通過循環。

#if defined _WIN32 || defined _WIN64
#include <windows.h>
#else
#include <dlfcn.h>
#endif

#include <iostream>
#include <cstdint>
#include <vector>
#include <functional>

class Library
{
    private:
        void* Module;

    public:
        Library(std::string Library);
        ~Library();

        template<typename T>
        T AddressOf(std::string FunctionName);

        template<typename T>
        bool AddressOf(T &FunctionDefinition, std::string FunctionName);

        template<typename T, typename ...Args>
        auto CallFunction(void* Function, Args... args) -> decltype(reinterpret_cast<T>(Function)(args...));
};

Library::Library(std::string Library)
{
    #if defined _WIN32 || defined _WIN64
    this->Module = LoadLibrary(Library.c_str());
    #else
    this->Module = dlopen(Library.c_str(), RTLD_LAZY);
    #endif
}

Library::~Library()
{
    #if defined _WIN32 || defined _WIN64
    FreeLibrary(static_cast<HMODULE>(this->Module));
    #else
    dlclose(this->Module);
    #endif
}

template<typename T>
T Library::AddressOf(std::string FunctionName)
{
    #if defined _WIN32 || defined _WIN64
    return reinterpret_cast<T>(GetProcAddress(static_cast<HMODULE>(this->Module), FunctionName.c_str()));
    #else
    return reinterpret_cast<T>(dlsym(this->Module, FunctionName.c_str()));
    #endif
}

template<typename T>
bool Library::AddressOf(T &FunctionDefinition, std::string FunctionName)
{
    return (FunctionDefinition = this->AddressOf<T>(FunctionName));
}

template<typename T, typename ...Args>
auto Library::CallFunction(void* Function, Args... args) -> decltype(reinterpret_cast<T>(Function)(args...))
{
    return reinterpret_cast<T>(Function)(args...);
}





std::vector<void*> Functions;

typedef void (*Message)(const LPCSTR sometext);
typedef void (*MessageEx)(const LPCSTR sometext, const LPCSTR title);
typedef int (*Add)(int X, int Y);
typedef int (*Subtract)(int X, int Y);

int main()
{
    Library L("TestDll.dll");
    std::array<std::string, 4> List = {"Message", "MessageEx", "Add", "Sub"};

    /** Get Function Addresses.. **/
    for (std::size_t I = 0; I < List.size(); ++I)
    {
        Functions.push_back(L.AddressOf<void*>(List[I]));
    }

    /** Call Functions.. **/
    L.CallFunction<Message>(Functions[0], "Hello World!");
    L.CallFunction<MessageEx>(Functions[1], "Hello World!", "DLL MessageBox Title");

    std::cout<<L.CallFunction<Add>(Functions[2], 5, 7)<<"\n";
    std::cout<<L.CallFunction<Subtract>(Functions[3], 7, 5)<<"\n";

    return 0;
}

有沒有重寫我的CallFunction類成員的更好方法,還是以某種方式保留函數簽名或將函數名稱映射到其簽名的方法? 我不介意寫出typedef,但我討厭不得不將它們作為模板參數,以便可以將其強制轉換為模數,因此,如果我能以某種方式讓vector存儲不同的函數簽名,則最好,但是歡迎任何解決方案。

編輯:為了清楚起見,我想以某種方式找出給定參數的函數簽名。 例如:

//If I do:

CallFunction<int>(FuncPtr, "Subtract", 10, 5);

//It would do:


template<typename T, typename ...Args>
auto Library::CallFunction(void* Function, Args... args) -> decltype(reinterpret_cast<T>(Function)(args...))
{
    return  //using args, figure out the function signature, call it, and return int.
}

在我看來,這似乎是人為的。 對於正確的名稱,您需要在正確的位置使用正確的參數的正確函數。 如果您聲明一個函數指針typedef ,並使用一行reinterpret_cast來分配該函數,那么在此之前,您需要一個40多個好的函數,然后再執行此處提供的代碼-這是簡單的步驟並重復輸入類型代碼,因此很容易遵循且易於維護。 沒有模板,沒有可變的爭論,等等。

顯然,您仍然必須產生一個從名稱返回void *的函數。 但這就是您現在減去reinterpret_cast

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM