call stack frame message dispatch

    public interface ICalculator

    {

        double Add(double x, double y);

        double Multiply(double x, double y);

    }

 

    [AttributeUsage(AttributeTargets.Class)]

    class PriorityProxyAttribute : ProxyAttribute

    {

        public override MarshalByRefObject CreateInstance(Type serverType)

        {

            MarshalByRefObject target = base.CreateInstance(serverType);

            RealProxy pp = new PriorityProxy(target, serverType);

            return (MarshalByRefObject)pp.GetTransparentProxy();

        }

    }

 

    [PriorityProxy]

    public class MyCalc : ContextBoundObject, ICalculator

    {

        public double Add(double x, double y) { return x + y; }

        public double Multiply(double x, double y) { return x * y; }

    }

 

class PriorityProxy : RealProxy

    {

        readonly MarshalByRefObject target;

 

        public PriorityProxy(MarshalByRefObject target, Type type)

            : base(type)

        {

            this.target = target;

        }

 

        public override IMessage Invoke(IMessage msg)

        {

            IMessage response = null;

            IMethodCallMessage call = (IMethodCallMessage)msg;

            IConstructionCallMessage ctor = call as IConstructionCallMessage;

 

            // To do some interception job…

            Console.WriteLine(call.MethodName);

 

            if (ctor != null)

            {

                RealProxy defaultProxy = RemotingServices.GetRealProxy(target);

                defaultProxy.InitializeServerObject(ctor);

                MarshalByRefObject tp = (MarshalByRefObject)this.GetTransparentProxy();

                response = EnterpriseServicesHelper.CreateConstructionReturnMessage(ctor, tp);

            }

            else

            {

                response = RemotingServices.ExecuteMessage(target, call);

            }

            return response;

        }

    }

 

class Program

    {

        static void Main(string[] args)

        {

            ICalculator calc = new MyCalc();

            double val1 = calc.Add(1, 2);

            double val2 = calc.Multiply(2, 3);

            Console.WriteLine("value1: {0}, value2: {1}", val1, val2);

        }

    }

 

This is an advanced method call mechinanism in .NET CLR (I believe in that it is the underlayer of .NET Remoting), which we call a method as if we were sending a message. Here, it is a real message!

 

As we all know, when we calling a method, a physical stack frame will be created, where arguments and return address will be push onto stack. This is very useful when a method is called inter domain/process. But, what if we want to call a remote object’s method, this is across domain/process? How can we do? Yes, just as something Web Services do, we can convert stack frame to a message (serialing it so as to transfer on network if necessary), and on the remote domain/process convert it back to stack frame. I believe in that it is what .NET Remoting does.

 

The key points of above demo code is,

  l  TransparentProxy: convert stack frame to message.

  l  ExecuteMessage: stack builder sink, convert message back to stack frame.

 

Furthermore, it is also an interception technique, that we can use to see what method of an object is called during the runtime. In the demo code above, Add and Multiply will be intercepted.

Convert IntPtr to Struct

[Q: how to reference members of a managed marshaled struct, that is pointed to by an IntPtr?]

Michael,

 

Use Marshal.PtrToStructure method is correct.

 

Recall managed IntPtr contains a value of native pointer, but the structure is not then marshal onto the managed one.

So try the following sample code,

 

1.       Define a native structure and function in NativeDll:

 

struct NATIVEDLL_API NativeStruct

{

          int a;

          int b;

};

 

extern "C" __declspec(dllexport) void* NativeFunction(void);

 

__declspec(dllexport) void* NativeFunction(void)

{

          static NativeStruct ns;

          ns.a = 10;

          ns.b = 20;

          return &ns;

}

 

2.       Marshal the accordant structure and declare the native function in managed code:

 

namespace IntPtrToStruct

{

    [StructLayout(LayoutKind.Sequential)] // not necessary here

    public struct ManagedStruct

    {

        public int a;

        public int b;

    }

   

    class Program

    {

        [DllImport("NativeDll.dll")]

        public static extern IntPtr NativeFunction();

 

        static void Main(string[] args)

        {

            IntPtr p = NativeFunction();

            ManagedStruct ms = (ManagedStruct)Marshal.PtrToStructure(p, typeof(ManagedStruct));

 

            Console.WriteLine(ms.a);

            Console.WriteLine(ms.b);

        }

    }

}

 

3.       Result of the output:

 

10

20

Press any key to continue . . .

 

Regards,

Austin