Re: Load an object reference onto the stack ???



"VivekR" <KenBase@xxxxxxxxx> wrote:

* In your example, does the runtime IL code call an instance method of
class App ?

The IL I generated calls a passed-in delegate. Delegates are objects which
have a method called "Invoke". When you call a delegate in C#, the
compiler compiles it as a call to the instance method "Invoke" on the
delegate instance.

So, in order for the IL to call this Invoke method in my example, it needs
to do three things:

* Load the object reference (i.e. the delegate) onto the stack. This will
be the 'this' reference for the method call later on.
* Load the arguments to the method call. In the case of my example, the
Invoke method's arguments are the same as the delegate's method arguments,
that is to say a single argument of type string.
* Actually invoke the (non-virtual) instance method "Invoke".

So, my code calls an instance method called "Invoke" on the object
reference "SomeMethod reference" passed as a parameter to the
CompileMethod method.

* And I do not exactly understand why you are using List<object>, which
will contain multiple objects in it.

The reason I used List<object> is because it grows automatically, and it
can be converted easily to an object[] with the method ToArray(). The
reason I use object[] as the 'this' pointer associated with the created
delegate (passed to DynamicMethod.CreateDelegate) is because it is a
general solution (i.e. it will work in all cases) to the problem: "How to
load an object reference onto the stack?", for any number of object
references of any type.

* Why are you comparing

?

* In the statements
cg.Emit(OpCodes.Ldarg_0);
cg.Emit(OpCodes.Ldc_I4, index);
cg.Emit(OpCodes.Ldelem_Ref);
When you Ldelem_Ref, do you mean to say that the value loaded is the
'this' [ie the App's object reference].

With 'ldarg 0' I'm loading the first argument to the function onto the
stack. This will be the object reference associated with the delegate
which was invoked. When I created the delegate with
DynamicMethod.CreateDelegate, I passed in an 'object[]' as the object
reference associated with the delegate. That means that an 'object[]'
reference is the first parameter passed to the function. (Make sure you're
fully aware of how .NET delegates work - they are a pair of (object
reference, method reference).)

With ldc.i4 <index> I'm loading the index to grab out of the array onto
the stack. And with ldelem.ref I'm copying the object reference at the
given index out of the object array and onto the stack.

* Summarizing my required in your example's terms
- App must create a dynamic method [it does using Dynamic
Method].
- The IL code in the dynamic method must call a instance
method, say CallBackMethod, of App. [I am not clear if it does].
And for calling the CallBackMethod, i need to load the
object reference of App, and call the method.

Bear with me for my ignorance, cuz i feel this one is complex and
pretty hard to debug where it fails.

OK. Here's a simpler example:

---8<---
using System;
using System.Reflection;
using System.Reflection.Emit;

class App
{
delegate void SomeMethod(string arg);

static void Main()
{
SomeMethod compiled = CreateCall(new App(), "TargetMethod");

compiled("Hello World!");
}

public void TargetMethod(string arg)
{
Console.WriteLine("Target Method got called with '{0}'.", arg);
}

static SomeMethod CreateCall(object reference, string methodName)
{
if (reference == null)
throw new NullReferenceException(
"'reference' can't be null.");

DynamicMethod result = new DynamicMethod("f", typeof(void),
new Type[] { reference.GetType(), typeof(string) },
typeof(App));

ILGenerator cg = result.GetILGenerator();

// load 'this', the reference instance
cg.Emit(OpCodes.Ldarg_0);
// load 'arg', the argument for the target method.
cg.Emit(OpCodes.Ldarg_1);

MethodInfo method = reference.GetType().GetMethod(methodName,
new Type[] { typeof(string) });
if (method == null)
throw new Exception(
string.Format("Method '{0}' not found.", methodName));

if (method.IsVirtual)
cg.Emit(OpCodes.Callvirt, method);
else
cg.Emit(OpCodes.Call, method);

cg.Emit(OpCodes.Ret);

return (SomeMethod) result.CreateDelegate(typeof(SomeMethod),
reference);
}
}
--->8---

-- Barry
.



Relevant Pages

  • Re: Invoiking delegates
    ... Invoke cannot be called directly on a delegate. ... is in fact a C# syntax benefit, but upon compilation it actually is turned ... But, it didn't tell anything about Invoke, BeginInvoke, etc methods. ... if not the reference of the Delegate class? ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Question on multicast delegates?
    ... > reference from delegate to invoke that mathod ... What exactly do you mean by "particular reference"? ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Generic Delegate Types explained (example)
    ... Unless you have specifically stated that the generic type has to be a value type, it can always be a reference type. ... To change the value of a string you have to replace it with a new string instance, which you can not do unless you send the string by reference to the method. ... example of generic delegate types taken from p. 108 of the C# 3.0 ... static Util UtilStringChanger2AndMoreStaticVersion ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: multithreaded tcp/ip monitoring application
    ... Passing a copy of a reference type variable just passes the reference, and so mutations in the instance can still be seen by multiple threads. ... The string type is a reference type, but a string instance is immutable and the string class is thread-safe. ... the variable itself is mutable and that's why you need the synchronization. ... But, and this is very important, the "str" variable itself is not referenced by the invoked delegate. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Threads & Garbage Collection
    ... A delegate contains a member called Target. ... giving out a reference to your object. ... valid reference to your management object until the thread goes away. ...
    (microsoft.public.dotnet.languages.csharp)