[Mono-dev] Marshal Variable length structure Array in Mono

Jonathan Pryor jonpryor at vt.edu
Tue Sep 6 07:26:29 EDT 2005


On Tue, 2005-09-06 at 12:50 +0200, Robert Jordan wrote:
> Indeed, variable length != variable count.
> But the returned structures must be manually marshaled:
> 
> http://www.pinvoke.net/default.aspx/winspool.EnumPrinters

They're trying *way* too hard.  This should work:

	struct NativePrinterInfo2 {
		public IntPtr pServerName;
		public IntPtr pPrinterName;
		/* ...
		   basically the PRINTER_INFO_2 struct with 
		   IntPtr instead of string...
		 */
	}

	[DllImport ("winspool")]
	public static extern bool EnumPrinters (
		uint Flags,
		string Name,
		uint Level,
		[Out] NativePrinterInfo2[] pPrinterEnum,
		uint cbBuf,
		out uint pcbNeeded,
		out uint pcReturned
	);

Usage:

	int printerInfoSize = Marshal.SizeOf (typeof(NativePrinterInfo2));
	uint needed, returned;
	if (!EnumPrinters (Flags, null, 2, null, 0, out needed, 
		out returned) {
		throw new Exception ();
	}
	NativePrinterInfo2[] data = 
		new NativePrinterInfo2[returned/printerInfoSize];
	if (!EnumPrinters (Flags, null, 2, data, returned, 
		out needed, out returned) {
		throw new Exception ();
	}
	PRINTER_INFO_2[] printers = new PRINTER_INFO_2[data.Length];
	for (int i = 0; i < printers.Length; ++i) {
		printers [i].pServerName = 
			Marshal.PtrToStringAnsi (data [i].pServerName);
		// ...
	}

*Much* simpler than manually digging through a returned byte array like
they did...

Supporting the other PRINTER_INFO_* structures is as easy as overloading
EnumPrinters and doing the same thing with the other structures.  Fairly
easy.

 - Jon





More information about the Mono-devel-list mailing list