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