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

问题描述

假设我在应用程序中具有某个函数的运行时内存地址,并且知道该函数的返回类型。是否可以使用可变参数模板调用函数,知道函数的返回类型,参数和调用约定?

模板化函数必须支持void和non-void返回类型。由于我们正在处理函数指针,因此即使返回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,2,3.f,"hello"); 
    // result should contain the int value we received by calling the function at 0x200

}

不幸的是,编译器引发错误C2440:无法将地址“地址”转换为“ ReturnType(__cdecl *)(int,int)”

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

谢谢您,祝您愉快!

解决方法

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

要强制编译器将地址强制转换为函数指针,您需要使用reinterpret_cast或c强制转换。

注意:您不正确地将整数地址转换为指针,因为您实际上是在尝试将包含地址的变量的地址转换为指针的地址,而不是地址本身!

所以这行:

function_caller<void>(&address,1,1); // Function with return type void.

应为:

function_caller<void>(address,1); // Function with return type void.

,并且始终使用地址类型为uintptr_t,该地址类型将适合该体系结构可用的任何地址(64位或32位)

,但是使用可变参数模板这样做根本不安全。原因是该函数具有这样的特定参数类型:

int fn(std::string& str,const char* ptr,uint64_t& i);

但是当您使用可变参数模板进行转换时,编译器将从传递的参数中推断出类型,但是可能需要进行一些转换!

所以在您当前的版本中:

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

因此,仅指定整个函数类型并像boost.dll那样使用它来强制转换地址确实是可靠的

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...