2013-06-02 48 views
0

在下面的代碼的方式,我試圖函數指針存儲在一個載體,但每個函數指針都有不同的簽名。是否有存儲不同的函數指針類型的容器

下面的代碼的想法是,當我加載一個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. 
} 
+0

有許多與此極其相似的問題,例如, http://stackoverflow.com/questions/8304582/how-to-store-functional-objects-with-difrent-signature-in-a-container-eg-std和http://stackoverflow.com/questions/4699018/如何對創建-A-容器-保持-不同類型-的函數指針合是c。你確定這不是重複的嗎? – jogojapan

+0

那麼沒有一個是相同的。它的類似,但他們都不想做我心裏想的那個:http://pastebin.com/PFWdr48Z – Brandon

回答

1

對我來說,這似乎是相當人爲的。您需要在正確的地方使用正確的參數,爲正確的名稱提供正確的功能。如果你聲明一個函數指針typedef,並使用單線reinterpret_cast分配的功能,你需要一個好的40+功能就看你在這裏提供的代碼之前 - 這是簡單的一個步驟,重複類型代碼,因此它很容易遵循並易於維護。沒有模板,沒有可變的參數,等等。

顯然,您仍然必須生成一個函數,該函數從名稱返回void *。但那只是你現在減去reinterpret_cast而已。

+0

我不明白:S我有一個函數指針的typedef。當我寫這篇文章時,我的想法是我想要做的事情是可能的。如果我有一個500+以上的導出文件,並想加載所有這些文件,我會創建一個字符串數組並一次加載全部不是?或者寫出500個typedefs並循環使用它? – Brandon

+0

你打算如何調用你的500個函數,大概不是所有的函數原型都是一樣的,所以大概不會有相同的參數? –

+0

Ahh沒有想到這一點。好吧,但我想避開不得不做: 「Hello World」 的 '無效的typedef(*留言)(LPCSTR消息);'' 消息m = L.AddressOf( 「信息」)'' M( );' 那消息M它在哪裏創建一個變量。會給我1000行,因爲每次出口我都必須分配給一個變量。現場直接分配給typedef將會容易很多。 – Brandon

相關問題