Introduction
The following article discusses how to achieve inline CIL (MSIL/IL) in the C# language as well as VB.NET. Using inline IL allows us to achieve things that the compiler usually prevents us from doing due to type-safety and other safety-checks. An example of such is VB.NET lacks native pointer support and you cannot declare generic-type pointers in C# or VB.NET.
The majority of this tutorial is in C#, but the tool itself supports VB.NET as well. Given you are a proficient enough programmer (which you are assumed to be if you're interested in using inline IL in your code) it is quite simple to understand how all of this applies to VB.NET.
You can learn how to use this tool to export methods to native code here.
How it works
Post-build-command line is triggered
ILDASM is ran which disassembles your compiled assembly
C#/VB.NET Project is analyzed for IL code
IL code is appropriately inserted into the file (disasm.il) produced by ILDASM
ILASM is ran which reassembles your decompiled assembly and produces a new *.pdb
Implementation
Let's take a look at a simple method in C#:
public static int Add(int n, int n2)
{
return n + n2;
}
Pulling out our handy tool ILSpy we can disassemble this method in a compiled assemble which yields the following:
.method public hidebysig static
int32 Add (
int32 n,
int32 n2
) cil managed
{
.maxstack 8
.locals init (
[0] int32 CS$1$0000
)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldarg.1
IL_0003: add
IL_0004: stloc.0
IL_0005: br.s IL_0007
IL_0007: ldloc.0
IL_0008: ret
}
Using ILSpy it's very easy to learn how C# or VB.NET does certain things at the IL level. Now, let's code an equivalent method in C# itself using the inline IL tool:
public static int Add(int n, int n2)
{
#if IL
ldarg n
ldarg n2
add
ret
#endif
return 0; // place holder so method compiles
}
As you can imagine, two integers which are arguments are loaded onto the pseudo stack, and then the instruction add pops both arguments off the pseudo stack and pushes the resulting value back onto the stack. You can learn more about operation codes using MSDN's articles for System.Reflection.Emit.OpCodes.
Using inline IL to achieve generic pointers
I've always thought C# lacked generic pointers. I think it's a tad silly you can apply the constraint class to a generic and assign null to a variable of T it but, if you applied the constraint struct you couldn't make a pointer variable of T. The reasoning is simple as structures can contain reference field types which you cannot (normally) create a pointer to, but there should still be a way to do this.
Read more: Codeproject
QR:
0 comments:
Post a Comment