Place an object on top of the stack in ILGenerator

I need to pass a function an instance of an object, so itโ€™s obvious that all the information that should be taken as an argument must be loaded onto the evaluation stack. Here is the code I'm looking for

someClass SomeObject = new someClass();

il.Emit(OpCodes.LoadObject, SomeObject);
il.Emit(OpCodes.CallVirt, MethodInfo Function);


public void Function(Object obj)
{
       Type type = typeof(obj);
       //do something w.r.t to the type
}

I do not require any information stored in the class, just a type, and I cannot use any of the primitive types to make my decision on

The last thing I read is that I can use a pointer to load a type using some opcode ... but I'm completely lost here, any help or pointers in the right direction would be great :)

[UPDATE]

Well, I found the answer to my question, tried it, and it works I donโ€™t know if this is the right way or not, but I can successfully create and load the object onto the stack and pass it to the function

ConstructorInfo ci = typeof(SomeClass).GetConstructor(System.Type.EmptyTypes);
IL.Emit(OpCodes.Newobj, ci);
IL.Emit(OpCodes.Call, SomeFunctionMethodInfo);

SomeFunctionMethodInfo - , , .

, MSDN, - ? , ,

+3
4

IL, IntPtr, :
    .
    . pin
    . .

, . ... , . . , , .

(, ) , ( ) object[] , DynamicMethod; MethodBuilder, TypeBuilder, ModuleBuilder, AssemblyBuilder .., , , .

, object[], , , . Invoke (DynamicInvoke ).

:

class SomeType { }
delegate void SomeDelegateType(params object[] args);
public class Program
{
    public static void Main()
    {
        var dn = new DynamicMethod("foo", (Type)null, new[] {typeof(object[])});
        var il = dn.GetILGenerator();
        il.Emit(OpCodes.Ldarg_0);
        il.Emit(OpCodes.Ldc_I4_0);
        il.Emit(OpCodes.Ldelem_Ref);
        il.EmitCall(OpCodes.Call, typeof(Program).GetMethod("Function"), null);
        il.Emit(OpCodes.Ret);
        var action = (SomeDelegateType)dn.CreateDelegate(typeof(SomeDelegateType));

        var obj = new SomeType();
        action(obj);
    }
    public static void Function(object obj)
    {
        Type type = obj.GetType();
        Console.WriteLine(type);
    }
}

, , , , , ()

object someObj = ...
Action action = () => Function(someObj);

:

class <>somehorriblename {
    public object someObj;
    public void SomeGeneratedName() { Function(someObj); }
}
...
var captureClass = new <>somehorriblename();
captureClass.someObj = ...
Action action = captureClass.SomeGeneratedName;
+4

, , GCHandle, IntPtr ( GCHandle.ToIntPtr), long integer ( ToPointer ToInt64).

, ILGenerator.Emit(OpCodes.Ldc_I8, ptr).

+3

, ( , ), , IL , , .

, () AppDomain, , () , IL, , .

, , -, - , Object[] ( ) , IL.

, , - ( " " ) ( IL, , , , ), IL , , , to ( ) .

. , IL , , , , . :

  • readonly (.. ), , IL. , .
  • ( , AppDomain). IL, , , . IL "set-and-forget", , DynamicMethod . : t213 > IL, , , , / DynamicMethod, , , .
  • "set-and-forget" , DynamicMethod .
  • , (, - ), , lock-free concurrency, Interlocked.Exchange ( SpinWait) , .
  • , , . , IL .
  • , , " ", , GC , .
+1

, . " " , IL DynamicMethod, 32- 64- .

, , , , /

, GCHandle; GC , , . , GCHandle, , DynamicMethod ( ) . GCHandle, , / .

, GCHandle (.. ) . , . , , , , / DynamicMethod, ; GCHandle (, ) , .

/// <summary>
/// Burn an reference to the specified runtime object instance into the DynamicMethod
/// </summary>
public static void Emit_LdInst<TInst>(this ILGenerator il, TInst inst)
    where TInst : class
{
    var gch = GCHandle.Alloc(inst);

    var ptr = GCHandle.ToIntPtr(gch);

    if (IntPtr.Size == 4)
        il.Emit(OpCodes.Ldc_I4, ptr.ToInt32());
    else
        il.Emit(OpCodes.Ldc_I8, ptr.ToInt64());

    il.Emit(OpCodes.Ldobj, typeof(TInst));

    /// Do this only if you can otherwise ensure that 'inst' outlives the DynamicMethod
    // gch.Free();
}

, , , Opcodes.Ldobj, Type , . , . bool, , System.Type , , true, Opcodes.Ldobj , .

TInst _inst = new MyObject();

// ...
il.Emit_LdInst(_inst);                  //  <-- the function shown above
il.Emit(OpCodes.Isinst, typeof(TInst));
il.Emit(OpCodes.Ldnull);
il.Emit(OpCodes.Ceq);
il.Emit(OpCodes.Ldc_I4_1);
il.Emit(OpCodes.Xor);

Ldc_I4/Ldc_I8 shove is Conv_I, , IntPtr.Size Ldc_I8 a long, x86. Opcodes.Ldobj .

. ( DynamicMethod), - . true, . ( , ...)

il.Emit_LdInst(cmp);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ceq);

, where TInst : class , . -, , . , , , Opcodes.Ldobj, , , , . , , - , 32 64 , . , a ValueType.

I tested all of this quite extensively on both x86 and x64 , debugging and releasing, and it works great without any problems. >

0
source

Source: https://habr.com/ru/post/1791932/


All Articles