[Mono-bugs] [Bug 28862][Wis] New - Runtime crashes Accessing a Structure that was Marshalled from a native Structure

bugzilla-daemon@rocky.ximian.com bugzilla-daemon@rocky.ximian.com
12 Aug 2002 18:50:24 -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 danmorg@sc.rr.com.

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

--- shadow/28862	Mon Aug 12 14:50:24 2002
+++ shadow/28862.tmp.27964	Mon Aug 12 14:50:24 2002
@@ -0,0 +1,125 @@
+Bug#: 28862
+Product: Mono/Runtime
+Version: unspecified
+OS: 
+OS Details: 
+Status: NEW   
+Resolution: 
+Severity: 
+Priority: Wishlist
+Component: misc
+AssignedTo: mono-bugs@ximian.com                            
+ReportedBy: danmorg@sc.rr.com               
+QAContact: mono-bugs@ximian.com
+TargetMilestone: ---
+URL: 
+Cc: 
+Summary: Runtime crashes Accessing a Structure that was Marshalled from a native Structure
+
+The runtime appears to crash when trying to access a C# struct that was 
+marshalled using PtrToStructure from a native C struct.
+
+The code I test comes from mcs/class/Mono.Data.MySql/Mono.Data.MySql
+
+Test.cs contains the test code which gets the native C struct, uses 
+Marshal.PtrToStructure() to marshal it to the C# struct 
+named Field, and accesses
+the data that is contained within that C# struct.
+
+Field.cs has the definition for the C# struct Field that is marshalled to.
+
+Mono.Data.MySql only runs under Cygwin at the moment and has been tested 
+and works with MySql 3.23 for Windows using the MySql client library 
+libmySQL.dll  Note, the original code that this was derived from works 
+under the Microsoft .NET Framework.
+
+Assembly Mono.Data.MySql.dll gets built like other assemblies:
+- in mcs: cd to class/Mono.Data.MySql
+- enter: ../../nant/NAnt.exe
+
+Make sure Mono.Data.MySql.dll and System.Data.dll are 
+at mcs/class/Mono.Data.MySql/Mono.Data.MySql
+
+To compile:
+monomcs Test.cs -r System.Data.dll Mono.Data.MySql.dll
+
+To run:
+monomono Test.exe
+
+Also, a table with the following needs to be created in the test database:
+CREATE TABLE SOMETABLE (
+  TID VARCHAR(8),
+  TCHAR VARCHAR(16),
+  AINT4 INT);
+
+=--- excerpt from Test.cs ---=
+
+public static int Main() {
+        string myStmt = "SELECT * FROM sometable";
+	IntPtr db = MySql.Init(IntPtr.Zero);
+	IntPtr conn = MySql.Connect(db, "", "", "", "", MySql.Port, "", 
+(uint)0);
+	int sdb = MySql.SelectDb(db, myDb);
+	int rcq = MySql.Query(db, myStmt);
+	procResults(db);
+}
+
+static void procResults(IntPtr db) {
+	IntPtr res = MySql.StoreResult(db);
+	int numRows = MySql.NumRows(res);
+	Console.WriteLine("Number of records found: " + numRows);
+	int numFields = MySql.NumFields(res);
+	string[] fields = new string[numFields];
+	for (int i = 0; i < numFields; i++) {
+		Field fd = (Field) Marshal.PtrToStructure(MySql.FetchField
+(res), typeof(Field));
+		fields[i] = fd.Name;
+	}
+	IntPtr row;
+	int recCnt = 1;
+	while ((row = MySql.FetchRow(res)) != IntPtr.Zero) {
+		Console.WriteLine("Record #" + recCnt + ":");
+		for (int i = 0, j = 1; i < numFields; i++, j++) {
+			Console.WriteLine("  Fld #"+j+" ("+fields[i]
++"): "+rowVal(row, i));
+			}
+		MySql.FreeResult(res);
+	}
+
+	static string rowVal(IntPtr res, int index) {
+		IntPtr str = Marshal.ReadIntPtr(res, index*IntPtr.Size);
+		if (str == IntPtr.Zero)
+			return "NULL";
+		string s = Marshal.PtrToStringAnsi(str);
+		return s;
+	}
+
+=--- excerpt from Field.cs ---=
+namespace Mono.Data.MySql {
+	using System.Runtime.InteropServices;
+	[StructLayout(LayoutKind.Sequential)]
+	public class Field {
+		[MarshalAs(UnmanagedType.LPStr)]
+		public string Name;
+
+		[MarshalAs(UnmanagedType.LPStr)]
+		public string Table;
+
+		[MarshalAs(UnmanagedType.LPStr)]
+		public string Def;
+
+		public int FieldTypes;
+		public uint Length;
+		public uint MaxLength;
+		public uint Flags;
+		public uint Decimals;	
+	}
+}
+
+MySql.cs contains the methods to pinvoke into the MySql client library.
+Excerpt:
+[DllImport("libmySQL",			 
+CharSet=System.Runtime.InteropServices.CharSet.Ansi,
+			 EntryPoint="mysql_thread_end", 
+ExactSpelling=true)]
+public static extern void ThreadEnd();