В функции типа EnumWindows в любом случае придется передавать адрес статического метода. тут не помогут ни интерфейсы, ни указатели на функции-члены. И хорошо если винда предусматривает аргумент через который можно передать this.
Код (Text): #define _STDCALL 0 #define _CCALL 1 extern "C" { void* make_shell(void*, void*, void*, int); } // __thiscall => __cdecl template <typename C, typename M, typename F> F method_cptr(C* class_ptr, M method_ptr) { return((F)make_shell(new char[512],&class_ptr,&method_ptr,_CCALL)); } // __thiscall => __stdcall template <typename C, typename M, typename F> F method_stdptr(C* class_ptr, M method_ptr) { return((F)make_shell(new char[512],&class_ptr,&method_ptr,_STDCALL)); } Код (Text): ; fasm-1.66 format MS COFF public _make_shell section '.code' readable executable ; fasm-1.66 ; Функция преобразует вызов __stdcall/__cdecl в __thiscall. shell_data: this_ptr = $-shell_data dd ? method_ptr = $-shell_data dd ? func_type = $-shell_data dd ? ret_addr = $-shell_data dd ? old_ecx = $-shell_data dd ? old_esp = $-shell_data dd ? shell_code: ; Сохранить ecx от повреждения push ecx ; Получить текущий адрес call get_eip get_eip: ; Переместится к полю данных sub dword [esp],get_eip-shell_data pop ecx ; Сохранить ecx pop dword[ecx+old_ecx] ; Адрес возврата pop dword[ecx+ret_addr] ; Сохранить указатель стека mov dword[ecx+old_esp],esp ; Загрузить this и вызвать метод push ecx add dword[esp],return-shell_data push dword[ecx+method_ptr] mov ecx,[ecx+this_ptr] ret ; Сюда вернется управление после вызова return: ; Получить текущий адрес call get_eip2 get_eip2: sub dword[esp],get_eip2-shell_data pop ecx ; __cdecl восстанавливает стек, его еще должна очистить ; вызывающая функция :) cmp dword [ecx+func_type],0 jz esp_ok mov esp,[ecx+old_esp] esp_ok: ; Загрузить адрес возврата push dword [ecx+ret_addr] ; Восстановить ecx mov ecx,[ecx+old_ecx] ret shell_end: ; fasm 1.66 ; Функия создания обертки ; void* make_shell(void* buffer, void* class, void* method, int type) _make_shell: push ebp mov ebp,esp push esi push edi push ecx ; Память для хранения функции (buffer) mov eax,[ebp+8] mov edi,eax ; Указатель this (c_ptr) mov eax,[ebp+12] mov esi,eax lods dword[esi] stos dword[edi] ; Указатель на метод (m_ptr) mov eax,[ebp+16] mov esi,eax lods dword[esi] stos dword[edi] ; Тип функции (type) mov eax,[ebp+20] stos dword[edi] ; Поля для ecx,esp,адреса возврата stos dword[edi] stos dword[edi] stos dword[edi] ; Копируем код функции mov esi,shell_code mov ecx,shell_end-shell_code rep movsb ; Возврашаем указатель на shell_code mov eax,[ebp+8] add eax,shell_code-shell_data ; Выход pop ecx pop edi pop esi pop ebp ret Код (Text): #include <stdio.h> #include "cppint.h" class A { public: int print_0(); int print_2(const char* s, int n); typedef (A::*t_mp0)(); typedef (A::*t_mp2)(const char*,int); }; int A::print_0() { return(printf("print_0\n")); } int A::print_2(const char* s, int n) { return(printf("print_2(%s,%d)\n",s,n)); } typedef int (*t_fn0)(); typedef int (*t_fn2)(const char*,int); typedef int (__stdcall *t_fn3)(const char*,int); void test_0(t_fn0 f) { f(); } void test_2(t_fn2 f) { f("One",1); } void test_std(t_fn3 f) { f("std",1); } int main() { A a; test_0( method_cptr<A,A::t_mp0,t_fn0>(&a, &A::print_0) ); test_2( method_cptr<A,A::t_mp2,t_fn2>(&a, &A::print_2) ); test_std( method_stdptr<A,A::t_mp2,t_fn3>(&a, &A::print_2) ); return(0); }