[Mono-bugs] [Bug 59136][Maj] New - Custom marshaling of pointers from managed to native returns an invalid address

bugzilla-daemon@bugzilla.ximian.com bugzilla-daemon@bugzilla.ximian.com
Wed, 26 May 2004 17:28:03 -0400 (EDT)


Please do not reply to this email- if you want to comment on the bug, go to the
URL shown below and enter your comments there.

Changed by patrick@vrac.iastate.edu.

http://bugzilla.ximian.com/show_bug.cgi?id=59136

--- shadow/59136	2004-05-26 17:28:03.000000000 -0400
+++ shadow/59136.tmp.19484	2004-05-26 17:28:03.000000000 -0400
@@ -0,0 +1,194 @@
+Bug#: 59136
+Product: Mono: Runtime
+Version: unspecified
+OS: 
+OS Details: Fedora Core 1
+Status: NEW   
+Resolution: 
+Severity: 
+Priority: Major
+Component: misc
+AssignedTo: mono-bugs@ximian.com                            
+ReportedBy: patrick@vrac.iastate.edu               
+QAContact: mono-bugs@ximian.com
+TargetMilestone: ---
+URL: 
+Cc: 
+Summary: Custom marshaling of pointers from managed to native returns an invalid address
+
+Description of Problem:
+
+With versions of Mono since 0.31, I have experienced problems when a custom
+marshaler is used to convert a C# object reference to a native pointer.  In
+my case, the C# reference contains a data member that is a pointer to
+natively allocated memory.  The custom marshaler's MarshalManagedToNative()
+simply returns the value of the contained pointer.  When the native code
+receives the pointer value as a function call parameter, the pointer value
+is consistently incremented by four bytes.  Hence, it points to the wrong
+memory address, and a segmentation fault occurs in the native code.
+
+Steps to reproduce the problem:
+1. Compile the included example code
+2. Run 'mono Test.exe'
+
+Actual Results:
+
+[C++] new_MyClass(): returning 0x9b69d00
+[C#] Test.MyClass.MyClass() received 0x9b69d00
+[C#] MyClassMarshaler.MarshalManagedToNative() obj: Test.MyClass
+     obj.mRawObject: 0x9b69d00
+[C++] handleMyClass(): received 0x9b69d04
+[C++] ERROR: Incorrect pointer value received from C#!
+
+Expected Results:
+
+[C++] new_MyClass(): returning 0x9b69d00
+[C#] Test.MyClass.MyClass() received 0x9b69d00
+[C#] MyClassMarshaler.MarshalManagedToNative() obj: Test.MyClass
+     obj.mRawObject: 0x9b69d00
+[C++] handleMyClass(): received 0x9b69d00
+
+How often does this happen? 
+
+This happens every time.
+
+Additional Information:
+
+I have included code that demonstrates the problem.  This code works with
+Mono versions up to 0.30.2 and with versions 1.0 and 1.1 of the .NET
+Framework.  It does not work with Mono 0.31 or Beta 1.
+
+*** Makefile ***
+# Linux
+CSC=            mcs /debug
+MAKE_DLL=       c++ -g -shared -o $@ $<
+LDFLAGS=        -L. -la_native
+NATIVE_DLL=     libnative.so
+ 
+# Windows
+#CSC=           csc /nologo /debug
+#MAKE_DLL=      cl /DWIN32 /nologo /EHsc $< /link /dll /out:$@
+#LDFLAGS=       /libpath:. a_native.lib
+#NATIVE_DLL=    native.dll
+ 
+all: Test.exe $(NATIVE_DLL)
+ 
+Test.exe: Test.cs
+        $(CSC) Test.cs
+ 
+$(NATIVE_DLL): native.cpp
+        $(MAKE_DLL)
+ 
+clean:
+        rm -f *.exe *.lib *.exp *.dll *.so *.pdb *.obj
+
+*** Test.cs ***
+using System;
+using System.Runtime.InteropServices;
+ 
+ 
+namespace Test
+{
+ 
+public class MyClass
+{
+   protected internal IntPtr mRawObject = IntPtr.Zero;
+ 
+   [DllImport("native", CharSet = CharSet.Ansi)]
+   private extern static IntPtr new_MyClass();
+ 
+   public MyClass()
+   {
+      mRawObject = new_MyClass();
+      Console.WriteLine("[C#] Test.MyClass.MyClass() received 0x{0:x}",
+                        mRawObject.ToInt32());
+   }
+ 
+   public void f() { }
+}
+ 
+public class MyClassMarshaler : ICustomMarshaler
+{
+   public void CleanUpManagedData(Object obj) { }
+ 
+   public void CleanUpNativeData(IntPtr nativeData) { }
+ 
+   public int GetNativeDataSize() { return -1; }
+ 
+   // Marshaling for managed data being passed to C++.
+   public IntPtr MarshalManagedToNative(Object obj)
+   {
+      Console.WriteLine("[C#] MyClassMarshaler.MarshalManagedToNative()
+obj: " + obj);
+      Console.WriteLine("     obj.mRawObject: 0x{0:x}",
+                        ((MyClass) obj).mRawObject.ToInt32());
+      return ((MyClass) obj).mRawObject;
+   }
+ 
+   // Marshaling for native memory coming from C++.
+   public Object MarshalNativeToManaged(IntPtr nativeObj) { return null; }
+ 
+   public static ICustomMarshaler GetInstance(string cookie) { return
+mInstance; }
+ 
+   private static MyClassMarshaler mInstance = new MyClassMarshaler();
+}
+ 
+public class Run
+{
+   [DllImport("native", CharSet = CharSet.Ansi)]
+   private extern static void handleMyClass(
+      [MarshalAs(UnmanagedType.CustomMarshaler,
+                 MarshalTypeRef = typeof(Test.MyClassMarshaler))]
+Test.MyClass obj);
+ 
+   public static void Main(String[] args)
+   {
+      MyClass obj = new MyClass();
+      handleMyClass(obj);
+   }
+}
+ 
+}
+
+*** native.cpp ***
+#include <iostream>
+ 
+#ifdef WIN32
+#define DLL_API __declspec(dllexport)
+#else
+#define DLL_API
+#endif
+ 
+class MyClass
+{
+public:
+   void f();
+};
+ 
+MyClass* gPtr(NULL);
+ 
+extern "C"
+{
+ 
+DLL_API MyClass* new_MyClass()
+{
+   gPtr = new MyClass();
+   std::cout << "[C++] new_MyClass(): returning " << std::hex << gPtr
+             << std::endl;
+   return gPtr;
+}
+ 
+DLL_API void handleMyClass(MyClass* obj)
+{
+   std::cout << "[C++] handleMyClass(): received " << std::hex << obj
+             << std::endl;
+ 
+   if ( obj != gPtr )
+   {
+      std::cout << "[C++] ERROR: Incorrect pointer value received from C#!"
+                << std::endl;
+   }
+}
+ 
+}