LINUX.ORG.RU

Привести функцию типа void(C::*method)(Args...) к void*

 , ,


0

2

Надо пихнуть вызов метода класса в asm. Для этого надо привести метод к void*.
Если использовать обычную C функцию, то все достаточно просто - (void)func, но с методами класса чета все не так просто.

Код:

	template<class C, class ...Args>
	bool hookMethod(int id, C *object, void(__attribute__((__thiscall__)) C::*method)(Args...)){
		if (!isIdValid(id))
			return false;

		CShortAsm *_asm = new CShortAsm();
		_asm->push(r86::ECX);
		_asm->mov(r86::ECX, (const int)object);
		_asm->jmp((void*)method);
		hookMethod(id, _asm->getAddr());

		return true;
	}
Компилятор ругается на строку
_asm->jmp((void*)method);

Ранее писал подобный код для коллбеков, и там все работает. Тут вроде ничем не отличается, а не работает. Не понимаю, что делаю не так.
Вызываются тоже одинаково:
g_class.DirectX->connect(this, &TestAntiInject::Present, proxyIDirect3DDevice9_Present);
testHook->hookMethod(25, this, &TestAntiInject::_RPC25);

★★★★★

У меня только предупреждение gcc выдаёт:

memfun-to-void-ptr.cpp:6:8: warning: converting from ‘void (A::*)()’ to ‘void*’ [-Wpmf-conversions]
     ext((void*)method);
Какой текст ошибки то?

xaizek ★★★★★ ()

В общем это анализатор clang'а выпендривается. Все компилируется

SR_team ★★★★★ ()
Ответ на: комментарий от tailgunner

Так-то да, но на мой взгляд странно, что эти два размера отличаются. По идее на одной платформе должны быть одинаковыми.

DELIRIUM ☆☆☆☆☆ ()
Ответ на: комментарий от DELIRIUM

А там точно не какой-нибудь толстый указатель?

__attribute__((__thiscall__))
O02eg ★★★★★ ()
Ответ на: комментарий от DELIRIUM

Так-то да, но на мой взгляд странно, что эти два размера отличаются.

Я смутно припоминаю, что размер указателя на функцию-член зависит от наличия виртуального наследования в иерархии.

tailgunner ★★★★★ ()
Ответ на: комментарий от tailgunner

Твоя правда. Может такое быть. Но я очень редко встречаю виртуальное наследование, за последние лет 8 может раза два видел. А работаю я C++-программистом с довольно крупными проектами.

DELIRIUM ☆☆☆☆☆ ()
Последнее исправление: DELIRIUM (всего исправлений: 1)

посмотрите в asm сгенерированном коде через С++, как выглядит вызов такой функции и поймет что это совсем не простой jump

anonymous ()

У метода класса как минимум есть неявный аргумент this. Кроме того, у класса может быть vtable.

andreyu ★★★★★ ()
struct CALL
{
   void cc(int i) { i++; }
   virtual void jump(void *obj, void (CALL::*m)(int) )
   { 
       (static_cast<CALL*>(obj)->*m)(9);
   }
};

int main()
{
    CALL cr;
    CALL *cl = &cr;
    cl->jump(cl, &CALL::cc);
    return 0;
}
CALL::jump(void*, void (CALL::*)(int)): # @CALL::jump(void*, void (CALL::*)(int))
  sub esp, 12
  mov ecx, dword ptr [esp + 20]
  mov eax, dword ptr [esp + 24]
  add ecx, dword ptr [esp + 28]
  test al, 1
  je .LBB7_2
  mov edx, dword ptr [ecx]
  mov eax, dword ptr [eax + edx - 1]
.LBB7_2:
  mov dword ptr [esp], ecx
  mov dword ptr [esp + 4], 9
  call eax
  add esp, 12
  ret
anonymous ()
Ответ на: комментарий от andreyu

Первый практически полный ответ в тему с использованием только терминов из стандарта С++. Весело тут среди «профессионалов», однако.

anonymous ()

В общем случае указатель на метод не обязан быть приводимым к void* и вообще быть по сути своей простым адресом в виртуальном адресном пространстве. Поэтому такой каст - неправомерен с точки зрения стандарта.

CatsCantFly ()
Последнее исправление: CatsCantFly (всего исправлений: 1)
Ответ на: комментарий от CatsCantFly

s/указатель на метод/\1 или функцию/

Deleted ()
Ответ на: комментарий от anonymous

У метода класса как минимум есть неявный аргумент this. Кроме того, у класса может быть vtable.

Первый практически полный ответ в тему с использованием только терминов из стандарта С++

Но ведь у указателя на метод нет неявного указателя this.

tailgunner ★★★★★ ()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от tailgunner

есть неявный аргумент this

Но ведь у метода нет неявного указателя this.

Не важно, что у него есть, толи аргумент, толи указатель. Главное же есть стандартизованный c++abi, что позволяет стоить стройные теории на знании sizeof с использованием стандартизированных ассемблерных инструкций.

anonymous ()
Ответ на: комментарий от anonymous

Не важно, что у него есть, толи аргумент, толи указатель

Это да. Ответ-то всё равно полный.

Главное же есть стандартизованный c++abi

Ну так сошлись на нужную главу стандартизированного C++ABI.

tailgunner ★★★★★ ()
Ответ на: комментарий от tailgunner

Это да.

Это да...же не смешно. Я расставил столько ловушек в сообщении, что знающий человек просто послал бы куда подальше и на этом закончил разговор. Придется самоустраниться. Успехов в освоении с++.

anonymous ()
Ответ на: комментарий от anonymous

Я расставил столько ловушек в сообщении

«В этом вашем интернете не поймешь, кто стебется, а кто правда дурак» (ц)

Придется самоустраниться

Можно было и не присоединяться.

tailgunner ★★★★★ ()
Ответ на: комментарий от tailgunner

Можно было и не присоединяться.

Я просто избирательно собираю статистику зависимости количества звезд и полезности сообщений их обладателей.

«В этом вашем интернете не поймешь, кто стебется, а кто правда дурак» (ц)

Пока можно сделать следующий вывод - полезность не зависит от количества звезд.

anonymous ()
Ответ на: комментарий от tailgunner

Пока можно сделать следующий вывод - полезность не зависит от количества звезд.

Это общеизвестный факт.

5 звезд не может ошибаться в фактах, тем более в общеизвестных.

anonymous ()
Ответ на: комментарий от BceM_IIpuBeT

Детектор сломался, нестите нового.

anonymous ()
Ответ на: комментарий от BceM_IIpuBeT

С чего бы вдруг? Во-первых, я терпеть не могу С++, а во-вторых, пишу грамотно, в отличие от товарища.

anonymous ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.