C++ 通过模板函数从其地址调用函数

C++ 通过模板函数从其地址调用函数,c++,templates,variadic-templates,C++,Templates,Variadic Templates,假设我在应用程序中有函数的运行时内存地址,并且我知道所述函数的返回类型,那么在知道函数返回类型、参数和调用约定的情况下,是否可以使用可变模板调用该函数 模板化函数必须同时支持作废和非作废返回类型。由于我们正在处理函数指针,编译器不应该抱怨,尽管返回ptr 我想做这样的事情: template<typename ReturnType, typename Address, typename... Args> ReturnType function_caller(Address addre

假设我在应用程序中有函数的运行时内存地址,并且我知道所述函数的返回类型,那么在知道函数返回类型、参数和调用约定的情况下,是否可以使用可变模板调用该函数

模板化函数必须同时支持作废和非作废返回类型。由于我们正在处理函数指针,编译器不应该抱怨,尽管返回ptr

我想做这样的事情:

template<typename ReturnType, typename Address, typename... Args>
ReturnType function_caller(Address address, Args... args)
{
    ReturnType(*ptr)(Args...) = address;
    return ptr(args...);
}
int main()
{
    auto address = 0x100;
    auto address2 = 0x200;
    function_caller<void>(&address, 1, 1); // Function with return type void.
    int result = function_caller<int>(&address2, 1, 2, 3.f, "hello"); 
    // result should contain the int value we received by calling the function at 0x200

}
模板
ReturnType函数_调用者(地址,Args…Args)
{
返回类型(*ptr)(参数…)=地址;
返回ptr(参数…);
}
int main()
{
自动地址=0x100;
自动地址2=0x200;
函数_调用者(&address,1,1);//返回类型为void的函数。
int result=function_调用者(&address2,1,2,3.f,“hello”);
//结果应该包含我们通过在0x200调用函数收到的int值
}
遗憾的是,编译器抛出了错误C2440:它无法将地址“
地址
”转换为“
返回类型(\uu cdecl*)(int,int)

我非常感谢你在这个问题上的帮助。我知道我可以将这个包装器分成两个函数:一个用于无效调用,另一个用于非无效调用,但我希望有一个更优雅、支持模板的解决方案


谢谢你,祝你今天愉快

答案是肯定的,但使用可变模板是危险的

要强制编译器将地址强制转换为函数指针,需要使用
reinterpret\u cast
或c cast

注意:您不正确地将整数地址强制转换为指针,因为您确实试图将包含指针地址的变量的地址强制转换为指针地址,而不是地址本身

所以这一行:

function_caller<void>(&address, 1, 1); // Function with return type void.
但是,当您使用可变模板强制转换时,编译器将根据传递的参数推断类型,但是可能需要进行一些转换

因此,在您当前的版本中:

int i;
function_caller<int>(0x15216516, "str", "ptr", i);
另请参见:

std::string to_string(std::string_view v);

function_caller<std::string>(0x15216516, "str"); // wrong the compiler won't convert the string literal for you and the function will end up with a dangling view

function_caller<std::string>(0x15216516, std::string("str")); // wrong again there is no conversion from std::string to std::string_view here

std::string to_string(std::string_视图v);
函数_调用者(0x15216516,“str”);//错误编译器不会为您转换字符串文字,函数将以悬空视图结束
函数调用方(0x15216516,std::string(“str”);//再次出错这里没有从std::string到std::string\u视图的转换

因此,只需指定整个函数类型并使用它来强制转换地址,就像boost.dll所做的那样,这才是真正可靠的

是的,我知道,地址不是真实的地址,只是为了显示概念。这不是我将在运行时使用的代码。请假设地址是正确的。除此之外,编译器不会介意,因为这是一个运行时错误,而不是编译时错误。自动推断参数也是危险的。第四个参数是
常量字符*
还是
常量字符[6]
?我很确定是后者。如果你愿意为void调用使用奇怪的语法,你也可以哄骗它来推断返回类型。不,这两个参数将是
const char[4]
,而不是
const char*
int i;
function_caller<int>(0x15216516, "str", "ptr", i);
int fn(const char*, const char*, int); // wrong types means stack corruptions and undefined behaviors
std::string to_string(std::string_view v);

function_caller<std::string>(0x15216516, "str"); // wrong the compiler won't convert the string literal for you and the function will end up with a dangling view

function_caller<std::string>(0x15216516, std::string("str")); // wrong again there is no conversion from std::string to std::string_view here