我会试着更好地解释一下我想做什么。 我读了一个带有函数签名的文件,我想创建一个指向每个函数的指针。
例如,一个如下所示的文件:
something.dll;int f(char* x, int y, SOMESTRUCT z)
something.dll;void g(void)
something.dll;SOMESTRUCT l(longlong w)
现在,在运行时我希望能够创建指向这些函数的指针(通过加载something.dll并使用GetProcAddress到这些函数)。
现在,GetProcAddress返回指向任意函数的FARPROC,但是如何在运行时使用FARPROC来调用这些函数? 据我所知,我需要将FARPROC转换为正确的签名,但我不能在运行时(或者至少我不知道如何)这样做。
有没有人知道如何设计呢?
谢谢! : - )
答案 0 :(得分:3)
函数类型在C ++中是编译时的,所以它不起作用,除非您可以提前定义所有类型。
< / LI>将参数推送到堆栈(本地变量就是这样)并将函数调用为void(__ cdecl *)(void)。
使用其他一些功能(如fastcall或thiscall)可能会出现问题。
更新:我实际上做了一个例子,它适用于键盘: (也适用于stdcall函数,因为在对齐堆栈分配后堆栈恢复)
#include <stdio.h>
#ifdef __GNUC__
#define NOINLINE __attribute__((noinline))
#define ALIGN(n) __attribute__((aligned(n)))
#else
#define NOINLINE __declspec(noinline)
#define ALIGN(n) __declspec(align(n))
#endif
//#define __cdecl
// Have to be declared __cdecl when its available,
// because some args may be passed in registers otherwise (optimization!)
void __cdecl test( int a, void* b ) {
printf( "a=%08X b=%08X\n", a, unsigned(b) );
}
// actual pointer type to use for function calls
typedef int (__cdecl *pfunc)( void );
// wrapper type to get around codepad's "ISO C++" ideas and gcc being too smart
union funcwrap {
volatile void* y;
volatile pfunc f;
void (__cdecl *z)(int, void*);
};
// gcc optimization workaround - can't allow it to know the value at compile time
volatile void* tmp = (void*)printf("\n");
volatile funcwrap x;
int r;
// noinline function to force the compiler to allocate stuff
// on stack just before the function call
NOINLINE
void call(void) {
// force the runtime stack pointer calculation
// (compiler can't align a function stack in compile time)
// otherwise, again, it gets optimized too hard
// the number of arguments; can be probably done with alloca()
ALIGN(32) volatile int a[2];
a[0] = 1; a[1] = 2; // set the argument values
tmp = a; // tell compiler to not optimize away the array
r = x.f(); // call the function; returned value is passed in a register
// this function can't use any other local vars, because
// compiler might mess up the order
}
int main( void ) {
// again, weird stuff to confuse compiler, so that it won't discard stuff
x.z = test; tmp=x.y; x.y=tmp;
// call the function via "test" pointer
call();
// print the return value (although it didn't have one)
printf( "r=%i\n", r );
}
答案 1 :(得分:2)
获得FARPROC
后,可以将FARPROC
转换为指向相应函数类型的指针。例如,你可以说
int (*fPtr)(char*, int, SOMESTRUCT) = (int (*)(char*, int, SOMESTRUCT))GetProcAddress("f");
或者,如果您想使用typedef
来简化此操作:
typedef int (*FType)(char *, int, SOMESTRUCT);
FType fPtr = (FType)GetProcAddress("f");
现在您已将函数指针存储在相应类型的函数指针中,您可以通过编写
来调用f
fPtr("My string!", 137, someStructInstance);
希望这有帮助!
答案 2 :(得分:2)
编译器需要知道确切的函数签名,以便为调用创建正确的设置和拆除。没有简单的方法可以伪造它 - 你从文件中读取的每个签名都需要一个相应的编译时签名来匹配。
您可以通过对编译器和某些汇编程序的深入了解来做您想做的事情,但我建议不要这样做。