Могу ли я создать функцию на основе другой функции во время выполнения? - PullRequest
0 голосов
/ 16 апреля 2011

Я играю с Microsoft Detours , чтобы перехватить API, например, я могу изменить то, что происходит, когда MessageBoxA называется так:

  int (WINAPI* pMessageBoxA)(HWND, LPCTSTR, LPCTSTR, UINT) = MessageBoxA;

  int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
  {
      printf("A function is called here!\n");
      return pMessageBoxA(hWnd, lpText, lpCaption, uType);  // call the regular MessageBoxA
  }

  DetourTransactionBegin();
  DetourUpdateThread(GetCurrentThread());
  DetourAttach(&(PVOID&)pMessageBoxA, MyMessageBoxA); 

Поэтому, когда вы звоните MessageBoxA, вы на самом деле звоните MyMessageBoxA.
Теперь я хочу написать функцию Hook(), которая будет делать то, что вышеупомянутые коды делают во время выполнения. Например, если я передам указатель функции MessageBoxA в функцию, она будет делать то же, что и код выше.
Конечно, я тоже могу передать указатель на другую функцию.
Тогда возникает вопрос: когда я получаю указатель на функцию в Hook, как я могу определить функцию с тем же возвращаемым значением и параметром, что и для данной функции (в данном случае, от MessageBoxA до int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)), а затем заполнить тело функции функции?

Ответы [ 2 ]

1 голос
/ 16 апреля 2011

В C ++ функции не являются первоклассным объектом , что означает, что они не могут быть созданы во время выполнения.

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

0 голосов
/ 16 апреля 2011

Что не совсем верно.Вы можете легко сохранить ссылку на функцию (член), чтобы можно было вызывать функцию другой функции (решаемой во время выполнения).

Вы также можете использовать functor, который представляет собой структуру / класс, загружающую ()оператор.Затем можно использовать состояние класса, чтобы запомнить, какую именно функцию вызывать.Пример функтора:

STL имеет заголовок <functional>, который содержит множество полезных утилит, чтобы сделать обработку (членских) ссылок на функции «проще» (немного).Случайный пример из cplusplus.com :

// mem_fun example
#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;

int main () 
{
  vector <string*> numbers;

  // populate vector of pointers:
  numbers.push_back ( new string ("one") );
  numbers.push_back ( new string ("two") );
  numbers.push_back ( new string ("three") );
  numbers.push_back ( new string ("four") );
  numbers.push_back ( new string ("five") );

  vector <int> lengths ( numbers.size() );

  transform (numbers.begin(), numbers.end(), lengths.begin(), mem_fun(&string::length));

  for (int i=0; i<5; i++) {
      cout << *numbers[i] << " has " << lengths[i] << " letters.\n";
  }
  return 0;
}

c ++ 0x имеет множество интересных новых функций (включая автоматическое определение типа и лямбда-выражения), которые сделают многоэто проще

...