указатель «сигнатура общей функции», который указывает на произвольную функцию - PullRequest
3 голосов
/ 25 марта 2011

Я постараюсь объяснить лучше, что я хочу сделать.Я читаю файл с сигнатурами функций и хочу создать указатель на каждую функцию.

Например, файл, который выглядит следующим образом:

something.dll;int  f(char* x, int y, SOMESTRUCT z)
something.dll;void g(void)
something.dll;SOMESTRUCT l(longlong w)

сейчас, во время выполнения я хочуиметь возможность создавать указатели на эти функции (загружая что-то.dll и используя GetProcAddress для этих функций).

Теперь GetProcAddress возвращает FARPROC, который указывает на произвольные функции, но как я могу использовать FARPROC для вызова этих функцийво время выполнения?Из того, что я знаю, мне нужно привести FARPROC к правильной подписи, но я не могу сделать это во время выполнения (или, по крайней мере, я не знаю, как).

Кто-нибудь знает, как спроектироватьсделать это?

Спасибо!: -)

Ответы [ 3 ]

3 голосов
/ 25 марта 2011
  1. Типы функций во время компиляции в C ++, поэтому он не будет работать, если вы не можете определить все типы, которые вы собираетесь использовать заранее.

  2. Это вопрос переноса аргументов в стек (и локальные переменные таковы) и вызова функции как void (__cdecl *) (void).

  3. С некоторыми другими видами функций (такими как fastcall или thiscall) это может быть более проблематично.

Обновление: я действительно сделал пример, и он работает на кодовой панели: (Такжеработает с функциями stdcall из-за восстановления стека после выравнивания выделенного стека)

http://codepad.org/0cf0YFRH

#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 );
}
2 голосов
/ 25 марта 2011

Компилятор должен знать точную сигнатуру функции, чтобы создать правильную настройку и разбор для вызова.Нет простого способа подделать его - каждая сигнатура, которую вы читаете из файла, будет нуждаться в соответствующей сигнатуре времени компиляции для сопоставления.

Вы можете делать то, что хотите, с глубоким знанием вашего компилятора и некоторыхассемблер, но я бы порекомендовал против этого.

2 голосов
/ 25 марта 2011

Получив FARPROC, вы можете привести FARPROC в указатель на соответствующий тип функции.Например, вы могли бы сказать

int (*fPtr)(char*, int, SOMESTRUCT) = (int (*)(char*, int, SOMESTRUCT))GetProcAddress("f");

Или, если вы хотите использовать typedef s, чтобы сделать это проще:

typedef int (*FType)(char *, int, SOMESTRUCT);
FType fPtr = (FType)GetProcAddress("f");

Теперь, когда у вас есть указатель функции, сохраненный вУказатель на функцию соответствующего типа можно вызвать f, написав

fPtr("My string!", 137, someStructInstance);

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...