我有以下代码:
typedef void * (__stdcall * call_generic)(...);
typedef void * (__stdcall * call_push2)(unsigned long,unsigned long);
void * pfunc;
// assume pfunc is a valid pointer to external function
// this is a logically correct way of calling, however this includes:
// add esp, 8
// after the call, and that breaks my stack.
((call_generic)pfunc)(1,1);
// however, if i use this call:
((call_push2)pfunc)(1,1);
// this does not happen and code works properly.
手动跟踪所有调用和计算 args 很痛苦(前面有很多这样的调用),我更喜欢为此使用宏或其他东西,但由于存在该错误,这是不可能的。
有解决办法吗?是否有另一种方法可以创建 call_generic
类型来执行此类操作?
我真的不明白为什么它会进行“清理”,但这会严重破坏我的堆栈,导致之前定义的变量丢失。
最佳答案
((call_generic)pfunc)(1,1);
只有在 pfunc
指向的函数实际上具有您转换的签名时才是逻辑上正确的调用方式到,void *(...)
。您的代码告诉编译器进行可变参数调用,因此它进行可变参数调用。对不是可变参数函数的函数的可变参数调用不起作用(在这种情况下,存在分歧,谁必须清理堆栈,并且完成了两次)。
没有办法免费做到这一点。在调用它之前,您必须以某种方式将函数指针转换为正确的签名,否则调用代码不知道如何以被调用代码可以使用的方式传递参数。
一个选项是确保pfunc
可能指向的所有被调用函数具有相同的签名,然后转换为该类型。例如,您可以将它们全部设为可变参数函数,但我并不特别推荐这样做。做你不想做的事情会更安全 - 确保所有可能出现在这里的函数都采用两个 unsigned long
,并转换为 call_push2
。
关于c++ - 通过指针调用具有未知参数计数的函数的简单方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7160146/