Кстати, а в .net есть API для генерации байткода, или проще сгенерировать CIL-текст а затем прогнать мелкософтовским ассемблером чтобы это дело собрал в байткод?
Есть. Написал примерчик:
class Program
{
public delegate void Procedure (int n);
public delegate void Executer (System.IntPtr pointer, int n);
public static readonly Executer executer;
public static readonly Procedure procedure;
static Program ()
{
System.Type Void = typeof(void);
System.Type Pointer = typeof(System.IntPtr);
System.Type Integer = typeof(System.Int32);
System.Reflection.Emit.DynamicMethod d = new System.Reflection.Emit.DynamicMethod("Executer",
Void, new System.Type[] { Pointer, Integer });
System.Reflection.Emit.ILGenerator g = d.GetILGenerator();
g.Emit(System.Reflection.Emit.OpCodes.Ldarg_1);
g.Emit(System.Reflection.Emit.OpCodes.Ldarg_0);
g.EmitCalli(System.Reflection.Emit.OpCodes.Calli,
System.Runtime.InteropServices.CallingConvention.StdCall, Void, new System.Type[] { Integer });
g.Emit(System.Reflection.Emit.OpCodes.Ret);
executer = (Executer)d.CreateDelegate(typeof(Executer));
procedure = Test;
}
public static void Test (int n)
{
System.Console.WriteLine("Test n={0}", n);
}
static void Main (string[] args)
{
System.IntPtr pointer = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate(procedure);
try
{
executer(pointer, 42);
}
catch (System.Exception e)
{
System.Console.WriteLine("Exception: {0}", e);
}
System.Console.ReadLine();
}
}
В этом примере я генерирую код процедуры Executer, которая будучи написанной на Си выглядела бы как-то так:
typedef void (__stdcall *Procedure)(int);
void Executer (void* pointer, int n)
{
((Procedure)pointer)(n);
}
То есть она принимает указатель void* приводит его к типу Procedure и вызывает передавая один аргумент.
Я вроде всё правильно написал, осталось только заставить программу заработать. Она, зараза, не хочет, кидает эксепшн:
Exception:
System.Security.VerificationException: Operation could destabilize the runtime.
at Executer(IntPtr , Int32 )
at Program.Main(String[] args) in D:\PROJECTS\Test\NativeFunctionPointerCallConsoleApplication\Program.cs:line 39
Справка говорит, что:
Исключение VerificationException генерируется, если в политику безопасности входит требование строгой типизации, а в ходе проверки невозможно определить, выполнено ли оно в коде.
Сижу думаю как же теперь отключить верификацию, которая по дефолту включена...