简体   繁体   English

有没有一种方法可以在容器中存储不同的函数指针类型

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

In the below code, I'm trying to store function pointers in a vector but each function pointer has a different signature. 在下面的代码中,我试图将函数指针存储在向量中,但是每个函数指针都有一个不同的签名。

The idea of the below code is that when I load a DLL, I simply use a loop to load all functions from the DLL into the vector. 以下代码的想法是,当我加载DLL时,我仅使用循环将DLL中的所有函数加载到向量中。 Then when I want to call a function, I just call it by name or index and pass a variable amount of arguments. 然后,当我想调用一个函数时,我只是按名称或索引来调用它,并传递可变数量的参数。 But I really want to call the functions the same way that I loaded them: via a loop. 但是我真的很想以与加载它们相同的方式调用这些函数:通过循环。

#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;
}

Is there a better way of re-writing my CallFunction class member or a way to retain function signature somehow or Map the name of the function to its signature? 有没有重写我的CallFunction类成员的更好方法,还是以某种方式保留函数签名或将函数名称映射到其签名的方法? I don't mind writing out the typedefs but I hate having to put them as the template argument so that it can cast to it so if I could somehow have the vector store different function signatures would be best but any solutions are welcomed. 我不介意写出typedef,但我讨厌不得不将它们作为模板参数,以便可以将其强制转换为模数,因此,如果我能以某种方式让vector存储不同的函数签名,则最好,但是欢迎任何解决方案。

EDIT: To make things clear, I want to somehow figure out the function signature given its arguments. 编辑:为了清楚起见,我想以某种方式找出给定参数的函数签名。 Ex: 例如:

//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.
}

To me, this seems rather contrived. 在我看来,这似乎是人为的。 You need the right function in the right place with the right arguments, for the right name. 对于正确的名称,您需要在正确的位置使用正确的参数的正确函数。 If you declare a function pointer typedef , and use a single line reinterpret_cast to assign the function, you need a good 40+ functions before it's up to the code you have provided here - and that's simple step and repeat type code, so it's easy to follow and easy to maintain. 如果您声明一个函数指针typedef ,并使用一行reinterpret_cast来分配该函数,那么在此之前,您需要一个40多个好的函数,然后再执行此处提供的代码-这是简单的步骤并重复输入类型代码,因此很容易遵循且易于维护。 No templates, no variable arguemnts, etc. 没有模板,没有可变的争论,等等。

Obviously, you'd still have to produce a function that returns a void * from a name. 显然,您仍然必须产生一个从名称返回void *的函数。 But that would be just what you have now minus the reinterpret_cast . 但这就是您现在减去reinterpret_cast

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM