Si vous utilisez MSVC et ciblez x86-32 (pas x86-64), vous pouvez utiliser la convention __stdcall pour la fonction de membre. (__cdecl fonctionne aussi)
Avec __stdcall ce sera passé comme premier paramètre, de sorte que vous pouvez écrire
typedef void(__stdcall *callback_t)(void* arg);
void set_callback(callback_t callback, void* callbackParameter);
struct Foo
{
int x;
void __stdcall someCallback() { this->x = 1; }
};
mais
Foo foo;
set_callback((callback_t)&Foo::someCallback, this);
ne fonctionnera pas: vous ne pouvez pas directement jeté Pointeur de fonction membre pointeur par standard. Vous devez utiliser une solution de contournement pour faire ce travail:
D'abord, affirmer que & Foo :: someCallback a la même taille que void *
static_assert(sizeof(&Foo::someCallback) == sizeof(void*), "");
// or assert()
Cette assertion peut échouer, s'il peut y avoir l'héritage multiple, et someCallback est virtuel. Pour désactiver l'héritage multiple, utilisez mot-clé __single_inheritance:
struct __single_inheritance Foo { /* ....*/ };
Deuxièmement, vous devriez jeter & Foo :: someCallback à callback_t en utilisant
union
{
void(__stdcall Foo::*src)();
callback_t dst;
} u = {&Foo::someCallback};
set_callback(u.dst, this);
ou
void(__stdcall Foo::*temp)() = &Foo::someCallback;
set_callback(*(callback_t*)&temp, this);
Il ne fonctionne que si vous pouvez passer ce au rappel en tant que premier paramètre.
Si vous ne pouvez pas, vous pouvez essayer de générer dynamiquement des talons de rappel dans l'assemblage :) Allouer une mémoire exécutable et il écrire
B9 XX XX XX XX mov ecx, <this>
68 XX XX XX XX push <function member address>
C3 ret
Il sera talon de rappel, qui convertira __stdcall à __thiscall.
C'est un peu déroutant mais je comprends le concept (je pense). –
Je l'ai maintenant. Je ne pense pas qu'il compilerait car callback_ a été déclaré après son utilisation dans call_some_func(); –
@Alexander: Les fonctions membres en ligne sont compilées comme si elles étaient définies immédiatement après la définition de leur classe. Donc, ce n'est pas un problème. – sbi