[Mono-bugs] [Bug 29548][Nor] New - Delegate/Callback defined in native code structure

bugzilla-daemon@rocky.ximian.com bugzilla-daemon@rocky.ximian.com
28 Aug 2002 05:45:15 -0000


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 jsohn@columbus.rr.com.

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

--- shadow/29548	Wed Aug 28 01:45:15 2002
+++ shadow/29548.tmp.18691	Wed Aug 28 01:45:15 2002
@@ -0,0 +1,202 @@
+Bug#: 29548
+Product: Mono/Runtime
+Version: unspecified
+OS: 
+OS Details: Windows XP, .NET Framework SDK, Mono from CVS (08/27/02)
+Status: NEW   
+Resolution: 
+Severity: 
+Priority: Normal
+Component: misc
+AssignedTo: mono-bugs@ximian.com                            
+ReportedBy: jsohn@columbus.rr.com               
+QAContact: mono-bugs@ximian.com
+TargetMilestone: ---
+URL: 
+Cc: 
+Summary: Delegate/Callback defined in native code structure
+
+Description of Problem:
+
+Delegate/Callbacks functions to native code do not appear to register
+properly when contained inside of a structure. I noticed the GTK# project
+makes extensive use of callbacks to native code but these functions are
+registered directly as parameters in the function call. This application
+(using the Win32 API) registers the callback function as a member of a
+WNDCLASS structure in the RegisterClass call as:
+
+    WNDCLASS wc = new WNDCLASS();  // WNDCLASS is a structure
+    // WndProc is a delegate
+    wc.lpfnWndProc = new WndProc(TestWndProc);
+    ... 
+    RegisterClassA(ref wc);  // this native call fails under Mono
+
+I've included the full sample below that reproduces this problem. It
+appears mcs compiles the application properly but Mono (using the mono
+command) is unable to produce the same results as the .NET SDK under Windows.
+
+Steps to reproduce the problem:
+1. compile application using: mcs Test.cs
+2. run under .NET in Windows: ./Test.exe (application runs as expected,
+ctrl-c cancels)
+3. run the same application under Mono: mono Test.exe (fails on the
+RegisterClass call)
+
+Actual Results:
+Under Mono The ouptut of the application is:
+error registering class
+
+Expected Results:
+The created window is displayed and "In TestWndProc" is displayed as
+messages are dispatched to the window. This runs as expected under the .NET
+Framework.
+
+How often does this happen? 
+
+
+Additional Information:
+
+The code that reproduces this problem is below. Under mono the
+RegisterClass call fails.
+
+Test.cs:
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace Test {
+
+	public class Test {
+
+		public delegate IntPtr WndProc (IntPtr hwnd, int msg,
+						IntPtr wParam, IntPtr lParam);
+
+		[StructLayout(LayoutKind.Sequential)]
+		public struct WNDCLASS {
+			public int style;
+			public WndProc lpfnWndProc;
+			public int cbClsExtra;
+			public int cbWndExtra;
+			public IntPtr hInstance;
+			public IntPtr hIcon;
+			public IntPtr hCursor;
+			public IntPtr hbrBackground;
+			public string lpszMenuName;
+			public string lpszClassName;
+		}
+
+		[DllImport ("kernel32.dll")]
+		public static extern IntPtr GetModuleHandleA (
+			string lpModuleName);
+
+		[DllImport ("user32.dll")]
+		public static extern IntPtr RegisterClassA (
+			ref WNDCLASS lpWndClass);
+
+		[DllImport ("user32.dll")]
+		public static extern IntPtr CreateWindowExA (
+			uint dwExStyle, string lpClassName, 
+			string lpWindowName, uint dwStyle, 
+			int x, int y, int nWidth, int nHeight,
+			IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance,
+			ref object lpParam);
+
+		[DllImport ("user32.dll")]
+		public extern static IntPtr DefWindowProcA (
+			IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
+
+		[DllImport ("user32.dll")]
+		public static extern int ShowWindow (IntPtr hWnd, 
+						     int nCmdShow);
+
+		[DllImport ("user32.dll")]
+		public static extern int GetMessageA (
+			ref int msg, IntPtr hwnd, int msgFrom,  int msgTo);
+
+		[DllImport ("user32.dll")]
+		public static extern int  TranslateMessage (ref int msg);
+
+		[DllImport ("user32.dll")]
+		public static extern int DispatchMessageA (ref int msg);
+
+		// Window Styles
+		public const uint WS_OVERLAPPED = 0x00000000;
+		public const uint WS_POPUP = 0x80000000;
+		public const uint WS_CHILD = 0x40000000;
+		public const uint WS_MINIMIZE = 0x20000000;
+		public const uint WS_VISIBLE = 0x10000000;
+		public const uint WS_DISABLED = 0x08000000;
+		public const uint WS_CLIPSIBLINGS = 0x04000000;
+		public const uint WS_CLIPCHILDREN = 0x02000000;
+		public const uint WS_MAXIMIZE = 0x01000000;
+		public const uint WS_CAPTION = 0x00C00000;
+		public const uint WS_BORDER = 0x00800000;
+		public const uint WS_DLGFRAME = 0x00400000;
+		public const uint WS_VSCROLL = 0x00200000;
+		public const uint WS_HSCROLL = 0x00100000;
+		public const uint WS_SYSMENU = 0x00080000;
+		public const uint WS_THICKFRAME = 0x00040000;
+		public const uint WS_GROUP = 0x00020000;
+		public const uint WS_TABSTOP = 0x00010000;
+		public const uint WS_MINIMIZEBOX = 0x00020000;
+		public const uint WS_MAXIMIZEBOX = 0x00010000;
+		public const uint WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | 
+		        WS_CAPTION | WS_SYSMENU | WS_THICKFRAME| 
+		        WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
+
+		public const uint SW_SHOW = 5;
+
+		static public IntPtr TestWndProc (IntPtr hwnd, int msg,
+				  IntPtr wParam, IntPtr lParam)
+		{
+			Console.WriteLine("In TestWndProc");
+			return DefWindowProcA(hwnd, msg, wParam, lParam);
+		}
+
+		static public void Main () 
+		{
+			WNDCLASS wc = new WNDCLASS();
+			IntPtr hWnd = (IntPtr) 0;
+			
+			wc.lpszClassName = "test";
+			wc.lpfnWndProc = new WndProc(TestWndProc);
+			wc.style = 0;
+			wc.hInstance = (IntPtr) 0;
+			wc.hIcon = (IntPtr) 0;
+			wc.hCursor = (IntPtr) 0;
+			wc.hbrBackground = (IntPtr) 0;
+			wc.lpszMenuName = "";
+			wc.cbClsExtra = 0;
+			wc.cbWndExtra = 0;
+			
+			if (RegisterClassA(ref wc) == (IntPtr) 0) {
+				Console.WriteLine("error registering class");
+				return;
+			}
+			
+			Object lpParam = new Object();
+			IntPtr hInstance = GetModuleHandleA (null);
+			
+			hWnd = CreateWindowExA ( 
+				0, "test", "test",
+				WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+				10, 10, 320, 200,
+				(IntPtr) 0, (IntPtr) 0, 
+				hInstance, ref lpParam);
+			
+			if (hWnd == (IntPtr) 0) {
+				Console.WriteLine("unable to create window");
+				return;
+			}
+
+			ShowWindow (hWnd, (int) SW_SHOW);
+
+			int msg = 0;
+
+			while (GetMessageA (ref msg, (IntPtr) 0, 0, 0) != 0) {
+				TranslateMessage (ref msg);
+				DispatchMessageA (ref msg);
+			}
+		}
+	}
+}