298 / 107 / 31
Регистрация: 12.03.2012
Сообщений: 449
1

Указатель на метод класса

21.04.2017, 06:09. Показов 2107. Ответов 16
Метки нет (Все метки)

Есть для этого какой-нибудь инструмент? Интересует именно не ссылка, а указатель. Хочется примерно следующего:

C++
1
2
3
4
5
6
7
8
9
10
11
typedef void(__thiscall*type_pfnTest)(int);
type_pfnTest g_pfnTest;
 
struct thiscall_funcs
{
    void _Test(int arg) { g_pfnTest(arg); }
}
 
//...
    Hook(g_pfnTest, &thiscall_funcs::_Test);
//...
Возможно ли что-то подобное?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
21.04.2017, 06:09
Ответы с готовыми решениями:

Как передать в метод класса Menu указатель на метод дочернего класса?
Как передать в метод базового класса указатель на метод дочернего: class Menu() { protected: ...

Функция, получающая указатель на обычную функцию, получает указатель на метод класса
Здравтсвуйте. Имеется вопрос по указателям на методы класса. Допустим, есть функция( f ), которая...

Указатель на метод класса в качестве аргумента метода класса
Функция _createFun вызывается для создания ХХХ в основном классе. Но вот потребовалось создать ХХХ...

Указатель на метод класса
Доброго времени суток, форумчане. Необходимо получить указатель на размер вектора. Делаю из...

16
Любитель чаепитий
3734 / 1793 / 563
Регистрация: 24.08.2014
Сообщений: 5,998
Записей в блоге: 1
21.04.2017, 06:36 2
Цитата Сообщение от h3mbr0 Посмотреть сообщение
Есть для этого какой-нибудь инструмент?
для чего?
конкретней задачу опиши.
0
298 / 107 / 31
Регистрация: 12.03.2012
Сообщений: 449
21.04.2017, 06:45  [ТС] 3
Да я же вроде и описал =)
Нужно сделать хук
В данный момент приходится делать так:
C++
1
2
3
4
5
6
7
8
9
    
void _Test (int arg)
{
    void *thisObj;
    __asm { mov thisObj, ecx }
//...
    __asm { mov ecx, thisObj }
    return g_pfnTest(arg);
}
И все бы ничего, но при определенных обстоятельствах ecx до начала кода не доходит, а делать naked wrap'перы для каждой функции будет геморно, да и очень уж неэстетично, не говоря уже об x64
0
Любитель чаепитий
3734 / 1793 / 563
Регистрация: 24.08.2014
Сообщений: 5,998
Записей в блоге: 1
21.04.2017, 06:49 4
Цитата Сообщение от h3mbr0 Посмотреть сообщение
Да я же вроде и описал
где?
непонятные хуки и обрывки кода показываешься какие-то пока что.
что за хук, что должен делать?
тебе нужен указатель на функцию-член или как?
почему тема так названа?

Цитата Сообщение от GbaLog-
тебе нужен указатель на функцию-член или как?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
 
struct A
{
    void foo(int) {}
};
 
int main()
{
    void (A::*ptr)(int) = &A::foo;
    
    A a;
    
    (a.*ptr)(1);
}
0
298 / 107 / 31
Регистрация: 12.03.2012
Сообщений: 449
21.04.2017, 06:58  [ТС] 5
Чуть более подробно:
Hook выглядит примерно так
C++
1
bool Hook(void**, void*);
В коде выше я, к слову, немного ошибся, и там не g_pfnTest а &g_pfnTest, а еще точнее (PVOID*)&g_pfnTest

Я на C++ не писал со времен выхода C++11, и не очень ориентируюсь в его терминах. Имел ввиду я примерно следующее:
вот этот самый указатель/ссылка/что бы то ни было
C++
1
void (A::*ptr)(int) = &A::foo;
нужно привести к PVOID. Компилятор этого не дает
По ту сторону Hook() это всего лишь адрес, факт того, что это __thiscall функция мне нужен только в пределах этого места

Как это должно работать: Hook перенаправляет оригинальную Test() (метод класса в другом исполняемом файле) в мою _Test(). При этом мне хотелось бы чтобы он не отжирал у меня указатель на this и я мог вызвать его оригинал по адресу через __thiscall (ну тут уже хоть через __stdcall с __asm { mov ecx, this } , это уже не так критично)

Не может же быть, что плюсовые методы хукаются таким грязным способом? Именно сами функции, а не vftable
0
Любитель чаепитий
3734 / 1793 / 563
Регистрация: 24.08.2014
Сообщений: 5,998
Записей в блоге: 1
21.04.2017, 07:03 6
Цитата Сообщение от h3mbr0 Посмотреть сообщение
нужно привести к PVOID.
как будешь там её использовать, если указатель тип потеряет свой?
0
298 / 107 / 31
Регистрация: 12.03.2012
Сообщений: 449
21.04.2017, 07:11  [ТС] 7
Цитата Сообщение от GbaLog- Посмотреть сообщение
как будешь там её использовать, если указатель тип потеряет свой?
Я же еще раз говорю: внутри Hook мне не важен тип указателя, там я патчу 5 байтиков на jmp по адресу, и будь это хоть __thiscall или __fastcall - не имеет значения, Hook делает свою работу. Т.е. мне нужно получить сам адрес. void*/uintptr_t/DWORD - не важно, но это должно быть число

Добавлено через 3 минуты
Еще раз на всякий случай: конечная цель заключается не в получении этого самого адреса, а в уменьшении мук с хуком метода класса
Если есть другой выход - может это даже лучше
0
Любитель чаепитий
3734 / 1793 / 563
Регистрация: 24.08.2014
Сообщений: 5,998
Записей в блоге: 1
21.04.2017, 07:36 8
Цитата Сообщение от h3mbr0 Посмотреть сообщение
Компилятор этого не дает
ну правильно, указатель на функцию-член весит больше, чем указатель на void.
0
298 / 107 / 31
Регистрация: 12.03.2012
Сообщений: 449
21.04.2017, 08:50  [ТС] 9
Цитата Сообщение от GbaLog- Посмотреть сообщение
ну правильно, указатель на функцию-член весит больше, чем указатель на void.
Это все хорошо, но вопрос то был о другом
Есть возможность получить адрес или другой способ сохранить this языковыми средствами?

Добавлено через 6 минут
Нащупал:
C++
1
2
3
4
    __asm {
        mov eax, thiscall_funcs::_Test
        mov pFunc, eax
    }
но неужели без __asm никак?

Добавлено через 45 минут
Цитата Сообщение от GbaLog- Посмотреть сообщение
ну правильно, указатель на функцию-член весит больше, чем указатель на void.
Только что осознал вами сказанное. С какой радости он весит больше то?
0
Любитель чаепитий
3734 / 1793 / 563
Регистрация: 24.08.2014
Сообщений: 5,998
Записей в блоге: 1
21.04.2017, 09:23 10
Цитата Сообщение от h3mbr0 Посмотреть сообщение
С какой радости он весит больше то?
http://www.cyberguru.ru/cpp/me... ?showall=1
раздел: ПОЧЕМУ УКАЗАТЕЛИ ФУНКЦИЙ-ЧЛЕНОВ НАСТОЛЬКО СЛОЖНЫЕ?
1
298 / 107 / 31
Регистрация: 12.03.2012
Сообщений: 449
21.04.2017, 09:35  [ТС] 11
Цитата Сообщение от GbaLog- Посмотреть сообщение
http://www.cyberguru.ru/cpp/member-f...html?showall=1
раздел: ПОЧЕМУ УКАЗАТЕЛИ ФУНКЦИЙ-ЧЛЕНОВ НАСТОЛЬКО СЛОЖНЫЕ?
Спасибо за ссылку
Нагуглил уже что размер часто разный, хотя мне кажется реализовать можно бы было и иначе
В любом случае, не вижу причину по которой нельзя получить адрес каким-нибудь явным_кастом. И безопасность не пострадала бы, и мучиться бы не пришлось. GCC позволяет, неужели славящийся своими костылями MSVC - нет?
0
Любитель чаепитий
3734 / 1793 / 563
Регистрация: 24.08.2014
Сообщений: 5,998
Записей в блоге: 1
21.04.2017, 09:41 12
Цитата Сообщение от h3mbr0 Посмотреть сообщение
не вижу причину по которой нельзя получить адрес каким-нибудь явным_кастом.
в void* не влезает адрес, куда пихать его собираешься?
0
298 / 107 / 31
Регистрация: 12.03.2012
Сообщений: 449
21.04.2017, 09:52  [ТС] 13
Цитата Сообщение от GbaLog- Посмотреть сообщение
в void* не влезает адрес, куда пихать его собираешься?
А адрес то как может не влезать? =) он удлиненный? может содержит CRC?
0
Любитель чаепитий
3734 / 1793 / 563
Регистрация: 24.08.2014
Сообщений: 5,998
Записей в блоге: 1
21.04.2017, 09:55 14
нашёл: Использование this в языке С++
1
298 / 107 / 31
Регистрация: 12.03.2012
Сообщений: 449
21.04.2017, 10:00  [ТС] 15
reinterpret_cast - одно из первого, что я попробовал. В MSVC не канает - увы, видимо как раз в том дело, что в нем указатель на метод - структура, хотя странно это, раз через __asm можно перекинуть. Но в любом случае спасибо за попытку помочь

Видимо, "красивого" способа тут нет, ну пусть хоть как макрос будет
Вдруг кому-нибудь пригодится:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#define GETMETHODADDR(dest, method) __asm { __asm push eax __asm mov eax, method __asm mov dest, eax __asm pop eax}
 
typedef void(__thiscall*type_pfnTest)();
type_pfnTest g_pfnTest;
 
struct thiscall_funcs{
    void _Test() { printf("Hooked\n"); g_pfnTest(); }
};
 
struct OriginalClass {
    void Test() { printf("Original\n"); }
};
 
int main()
{
    uintptr_t pFunc;
 
    GETMETHODADDR(pFunc, thiscall_funcs::_Test);
    GETMETHODADDR(g_pfnTest, OriginalClass::Test);
 
    Hook((void**)&g_pfnTest, (void*)pFunc);
 
    (new OriginalClass)->Test();
}
0
Любитель чаепитий
3734 / 1793 / 563
Регистрация: 24.08.2014
Сообщений: 5,998
Записей в блоге: 1
21.04.2017, 10:08 16
какая у тебя версия студии?
всё работает: http://rextester.com/RTH3043
1
298 / 107 / 31
Регистрация: 12.03.2012
Сообщений: 449
21.04.2017, 10:23  [ТС] 17
Немного невнимательно посмотрел: там к void* кастуется указатель на указатель на метод, а не ... ну вы поняли
Это в студии работает, правда после выполнения вылетает RTE нарушения стека почему-то
Тема адреса там не раскрыта, видимо, по-другому действительно никак, только суровый asm

Добавлено через 3 минуты
А нет, снова невнимательно посмотрел =) Видимо, ночью надо было спать
если его привести к uintptr_t* и разыменовать - получим адрес
Итог:
C++
1
uintptr_t pFuncAddr = *reinterpret_cast<uintptr_t*>(&pFunc);
Спасибо за помощь

Добавлено через 1 минуту
P.S. напридумали же, блин, плясок с этими кастами
макрос лаконичнее в итоге выглядит

Добавлено через 7 минут
Окончательный итог:
C++
1
auto GetMethodAddr = [](auto pFunc) { return *reinterpret_cast<uintptr_t*>(&pFunc); };
Вот теперь удобно =)
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
21.04.2017, 10:23
Помогаю со студенческими работами здесь

Указатель на метод класса
Как сделать указатель на метод класса А, который наследует класс В в классе В. class A : B...

Указатель на метод класса!
Ответьте пожалуйста на такой вопрос:Возможна ли такая ситуация и как ее реализовать правильно? Мне...

Указатель на метод класса
Собственно, проблема вот в чем. Есть класс и для него определен метод class ABC ....... public:...

Указатель на метод класса
Программа отказывается присваивать метод класса указателю. Как исправить? test.cpp: In function...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru