[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;
+ }
+}
+
+}