Re[3]: Преобразование указателей
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.07.01 20:24
Оценка: -1
Здравствуйте Нартов Андрей Евгеньевич, вы писали:

A>>уточните зачем это надо.

НАЕ>например, сделать нить (CreateThread()) из нестатической member function

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

Общая идея такова — записываем указатель на фунцию и на this экземпляра объекта в структуру.
И эмулируем вызов функции. Вот код:

// Структура для передачи указателя на функцию класса
struct CUniversalFuncPtr
{
void * pF; // Указатель на функцию класса
// Заметьте — это простой указатель на начало области
// кодом занимаемой кодом функции.

void * pThis; // Указатель на this экземпляр класса
};

// Подопытный кролик. :)
class CClass
{
public:
void f1(int i)
{
printf("i = %d, m_i = %d", i, m_i);
}
int m_i;
};

// Функция динамически вызывающаяя функцию любого класса.
// UniversalFuncPtr — унивирсальный указатель :))
// i — параметр передаваемый в вызываемую функцию.
void SomeCaller(CUniversalFuncPtr UniversalFuncPtr, int i)
{
__asm
{
// Эмулируем thiscall
mov ecx, UniversalFuncPtr.pThis;
mov eax, UniversalFuncPtr.pF;

push i ; // закладываем значение параметра
call eax // ecx->f1(i);
}
}

int main(int argc, char* argv[])
{
// Создаем переменную — подопытного кролика...
CClass c1;
// и инициализируем ее переменную-член...
c1.m_i = 123456;


// Поулучаем указатель на функцию некоторого класса.
// Совершенно неважно какой это класс, главное что функция
// должна быть описанна как:
// void FuncName(int);
typedef void ( CClass::*pmfnP)(int);
pmfnP pFunction = &CClass::f1;

CUniversalFuncPtr UniversalFuncPtr;
// Закладываем указатель на объекта (this)
UniversalFuncPtr.pThis = (void*)&c1;
// Закладываем указатель на функцию
__asm { mov eax, dword ptr pFunction }
__asm { mov UniversalFuncPtr.pF, eax }
// Приведенные выше операторы аналогичны конструкции:
// UniversalFuncPtr.pF = (void*)pFunction;
// но к сожалению такая конструкция вызывает сообщение об ошибке:
// error C2440: 'type cast' : cannot convert from
// 'void (__thiscall CClass::*)(int)' to 'void *'

// ...

SomeCaller(UniversalFuncPtr, 55555);

getchar();

return 0;
}
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.