fork(1) download
  1. using System;
  2. using System.Reflection;
  3. using System.Threading;
  4. using System.Runtime.InteropServices;
  5.  
  6. namespace TestTwoDomainsAndSingeThread
  7. {
  8. //[StructLayout(LayoutKind.Explicit)]
  9. public unsafe struct Variant
  10. {
  11. //[FieldOffset(0)]
  12. public ushort vt;
  13. //[FieldOffset(0)]
  14. public ushort wReserved1;
  15. //[FieldOffset(0)]
  16. public ushort wReserved2;
  17. //[FieldOffset(0)]
  18. public ushort wReserved3;
  19. //[FieldOffset(0)]
  20. public IntPtr bstrVal;
  21. //[FieldOffset(0)]
  22. public Int32 data01;
  23. //[FieldOffset(0)]
  24. public Int32 data02;
  25. }
  26.  
  27. public class Worker : MarshalByRefObject
  28. {
  29. public unsafe IntPtr GetIntPtrForVariant()
  30. {
  31. Variant v = new Variant();
  32. IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
  33. return pNative;
  34. }
  35.  
  36. public unsafe object GetDoubleFromAnotherDomain()
  37. {
  38. double obj = 3.14;
  39. AppDomain yad = AppDomain.CreateDomain("Yet another domain");
  40. Worker remoteWorker = (Worker)yad.CreateInstanceAndUnwrap(
  41. typeof(Worker).Assembly.FullName,
  42. typeof(Worker).FullName);
  43. IntPtr pNative = remoteWorker.GetIntPtrForVariant();
  44.  
  45. Marshal.GetNativeVariantForObject(obj, pNative);
  46.  
  47. object o = Marshal.GetObjectForNativeVariant(pNative);
  48. return o;
  49. }
  50. }
  51.  
  52. public class Test
  53. {
  54. static unsafe void Main(string[] args)
  55. {
  56. double obj = 3.14;
  57. AppDomain ad = AppDomain.CreateDomain("New domain");
  58. Worker remoteWorker = (Worker)ad.CreateInstanceAndUnwrap(
  59. typeof(Worker).Assembly.FullName,
  60. typeof(Worker).FullName);
  61. IntPtr pNative = remoteWorker.GetIntPtrForVariant();
  62.  
  63. Marshal.GetNativeVariantForObject(obj, pNative);
  64.  
  65. Variant result = (Variant)Marshal.PtrToStructure(pNative, typeof(Variant));
  66. Console.WriteLine("VarEnum.VT_R8 name from default domain: " + VarEnum.VT_R8);
  67. Console.WriteLine("Result of (VarEnum)result.vt from another domain: " + (VarEnum)result.vt);
  68. if (VarEnum.VT_R8 != (VarEnum)result.vt)
  69. {
  70. Console.WriteLine("Testcase failed");
  71. } else {
  72. Console.WriteLine("Testcase passed");
  73. }
  74.  
  75. AppDomain ndfD = AppDomain.CreateDomain("New domain for double");
  76. Worker remoteWorker2 = (Worker)ndfD.CreateInstanceAndUnwrap(
  77. typeof(Worker).Assembly.FullName,
  78. typeof(Worker).FullName);
  79.  
  80. object o = remoteWorker2.GetDoubleFromAnotherDomain();
  81. Console.WriteLine("3.14 value from default domain: " + obj.ToString());
  82. Console.WriteLine("3.14 value from remote domain: " + o);
  83. if (obj.ToString() != o.ToString())
  84. {
  85. Console.WriteLine("Testcase failed");
  86. } else {
  87. Console.WriteLine("Testcase passed");
  88. }
  89.  
  90. Console.WriteLine("Obj value cast: " + *((ulong*)&obj));
  91. Console.WriteLine("Unwound variant value cast: " + *((ulong*)&result.bstrVal));
  92.  
  93. Console.ReadLine();
  94. }
  95. }
  96. }
Success #stdin #stdout 0.71s 36528KB
stdin
Standard input is empty
stdout
VarEnum.VT_R8 name from default domain: VT_R8
Result of (VarEnum)result.vt from another domain: VT_R8
Testcase passed
3.14 value from default domain: 3.14
3.14 value from remote domain: 3.14
Testcase passed
Obj value cast: 4614253070214989087
Unwound variant value cast: 4614253070214989087