|
>>>Jonathan Pryor <[EMAIL PROTECTED]> 09/06/04 4:57 pm >>>
>Correctness depends upon the ListLocalPrinters() documentation. What is
>`printerList' supposed to be? Just a pointer to a
>CupsPrinterListStruct*? Or should it be an array of pointers? How many
>elements will be addressed?
Thanks for your insights and observations - very informative. As you
deduced, "printerList" is a pointer to a CupsPrinterListStruct*. I
modified the wrapper implementation to use "unsafe" code but still
unsuccessful in retrieving properties from the C# structure below.
The unmanaged ListLocalPrinters is returning a list containing 1
element yet the loop in PrintLibWrapper.ListLocalPrinters is executed
twice, throwing a NullReferenceException when "printer = printer->nextElement"
is executed on the second pass. Further, a NullReferenceException is
thrown on the first iteration through the loop by simply invoking
"Console.WriteLine("PrinterInfo: {0}, {1}", pl.Name, pl.Uri)".
I have tried several attributes on the structure elements with no change
in behavior. I believe the problem is in the marshalling attributes, but
I have yet to discover how to examine the memory in mono on linux.
Installing/configuring a windows client and running/debugging there
may be the easiest path.
Thanks again for the help.
Jim
// interop struct
[ StructLayout(LayoutKind.Sequential) ]
private�unsafe�struct�InternalPrinterList
{
[MarshalAs(UnmanagedType.ByValTStr/*LPStr*/, SizeConst=1024)]
public string printerUri;
[MarshalAs(UnmanagedType.ByValTStr/*LPStr*/, SizeConst=1024)]
public string printerCupsUri;
[MarshalAs(UnmanagedType.ByValTStr/*LPStr*/, SizeConst=1024)]
public string printerName;
[MarshalAs(UnmanagedType.ByValTStr/*LPStr*/,SizeConst=81)]
public�string�printerMakeModel;
[MarshalAs(UnmanagedType.U4)]
public InternalPrinterList *nextElement;
}
// Convert linked list constructed by unmanaged code to
// array of user-visible PrinterList objects.
public static unsafe PrinterList[] ListLocalPrinters()
{
IntPtr list = IntPtr.Zero;
try
{
ListLocalPrinters(ref list);
InternalPrinterList* printer = (InternalPrinterList *)list;
ArrayList printers = new ArrayList();
while (printer != null)
{
PrinterList pl = new PrinterList();
pl.Uri = printer->printerUri;
pl.CupsUri = printer->printerCupsUri;
pl.Name = printer->printerName;
pl.MakeModel = printer->printerMakeModel;
// throws NullReferenceException
Console.WriteLine("PrinterInfo: {0}, {1}", pl.Name, pl.Uri);
printers.Add(pl);
// Something not right here as we will go through again
// even when list contains only 1 element.
printer = printer->nextElement;
}
PrinterList[] rval = new PrinterList[printers.Count];
printers.CopyTo(rval);
return rval;
}
catch (Exception e)
{
return new PrinterList[0];
}
finally
{
if (list != IntPtr.Zero)
FreeLocalPrinterList(list);
}
}
|
