Bonjour,
Quelqu'un a déjà utilisé du il.Emit pour générer des méthodes au runtime ?
Il faut forcément un délégate pour appeler la méthode ainsi générée ?
En C++/CLI je peux aussi récupérer un pointeur de méthode, non ? (avec InteropServices.Marshal.GetFunctionPointerForDelegate ou MethodInfo RuntimeMethodHandle.GetFunctionPointer ?)
Ici je voudrais faire un générateur dynamique de stub interprété->compilé, c'est à dire un stub qui permet appeler une méthode en lui passant un tableau de paramètres (donc exactement ce que fait MethodInfo.Invoke mais en plus efficace en terme de perf vu que MethodInfo.Invoke fait plein de choses "inutiles", alors qu'un stub ne fait que 10 instructions MSIL) :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
/// classe et méthode compilée
ref class A {
String^ UneMethode(Int32 k, array<Type^> t) {
/* ... */
}
};
/// classe qui génère des stub
ref class StubFactory {
D^ GenerateStubFor(MethodInfo ^m) {
il.Emit(...)
il.Emit(...)
}
/// méthode générée dynamiquement avec il.Emit
static Object^ A_UneMethode_Stub(Object^ obj, array<Object^>^params) {
// implémentation en C++/CLI en guise d'exemple, c'est en MSIL qu'il
//faut savoir la coder pour pouvoir la générer dynamiquement
return (*((A^*)&obj))->UneMethode((Int32)params[0],(array<Object^>^)params[1]);
/// le cast *((A^*)&obj)) est un static_cast : il permet d'éviter le dynamic_cast qui fait le runtime check du type (qui est coûteux si on sait déjà à l'avance que le type est bon).
/// Pour params[0] et params[1] je pense qu'on ne peut pas y échapper.
}
}; |
Je m'étonne de ne pas trouver sur google quelqu'un qui aurait déjà codé la même chose.
Je pense que StubFactory.GenerateStubFor devrait renvoyer un D^ qui serait un type de delegate :
delegate Object ^ D(Object^ obj, array<Object^>^params);
Ensuite, j'aimerais aussi faire la même chose pour PropertyInfo/FieldInfo.Get/Set Value.
Une dernière question : c'est compliqué d'appeler une méthode C++ native __stdcall depuis du IL généré avec il.Emit ?
Je pense m'en sortir en utilisant ILdasm sur des bouts de code C++/CLI très simple me servant d'exemple
Une toute dernière question : est-ce qu'il faut vraiment générer dynamiquement (avec il.emit) un stub par méthode, ou est-ce qu'il serait possible d'écrire, statiquement, donc sans passer par il.emit, une seule méthode (entièrement écrite en MSIL) qui pour n'importe quel type de méthode arrive à pousser le tableau de paramètre sur la pile et à faire le call ?
A mon avis pour écrire un champ d'un objet on est obligé de passer par il.Emit (il n'y a aucune fonction de la réflection qui donne l'offset runtime d'un champ, donc impossible de faire une fonction générique capable d'écrire/lire un champ)
Partager