gpt4 book ai didi

c++ - 有没有办法在容器中存储不同的函数指针类型

转载 作者:太空宇宙 更新时间:2023-11-04 11:54:12 25 4
gpt4 key购买 nike

在下面的代码中,我试图将函数指针存储在一个 vector 中,但每个函数指针都有不同的签名。

下面代码的想法是,当我加载一个 DLL 时,我只是使用一个循环将 DLL 中的所有函数加载到 vector 中。然后当我想调用一个函数时,我只需按名称或索引调用它并传递可变数量的参数。但我真的很想以与加载函数相同的方式调用函数:通过循环。

#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

关于c++ - 有没有办法在容器中存储不同的函数指针类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16880553/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com