[Mono-list] Memory Allocation in unmanaged code
Jim Fehlig
jfehlig@novell.com
Wed, 08 Sep 2004 15:43:48 -0600
This is a MIME message. If you are reading this text, you may want to
consider changing to a mail reader or gateway that understands how to
properly handle MIME multipart messages.
--=__Part6F4F1C04.0__=
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
>>>Jonathan Pryor <jonpryor@vt.edu> 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);
}
}
--=__Part6F4F1C04.0__=
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<html>
<head>
=20
</head>
<body style=3D"margin-bottom: 1px; margin-right: 4px; margin-left: 4px; =
margin-top: 4px">
<DIV> >>>Jonathan Pryor <jonpryor@vt.edu> 09/06/04 =
4:57 pm >>>
<DIV> </DIV>
<DIV> >Correctness depends upon the ListLocalPrinters() =
documentation.  What is
<DIV>>`printerList' supposed to be?  Just a pointer to a
<DIV>>CupsPrinterListStruct*?  Or should it be an array =
of pointers?  How many
<DIV>>elements will be addressed?
<DIV> </DIV>
<DIV>
Thanks for your insights and observations - very informative. =
As you
</DIV>
<DIV>
deduced, "printerList" is a pointer to a CupsPrinterListStr=
uct*. I
</DIV>
<DIV>
modified the wrapper implementation to use "unsafe" code =
but still
</DIV>
<DIV>
unsuccessful in retrieving properties from the C# structure below.
</DIV>
<DIV>
The unmanaged ListLocalPrinters is returning a list containing 1
</DIV>
<DIV>
element yet the loop in PrintLibWrapper.ListLocalPrinters is =
executed
</DIV>
<DIV>
twice, throwing a NullReferenceException when "printer =3D =
printer->nextElement"
</DIV>
<DIV>
is executed on the second pass. Further, a NullReferenceExcepti=
on is
</DIV>
<DIV>
thrown on the first iteration through the loop by simply invoking
</DIV>
<DIV>
"Console.WriteLine("PrinterInfo: {0}, {1}", pl.Name, =
pl.Uri)".
</DIV>
<DIV>
I have tried several attributes on the structure elements with no =
change
</DIV>
<DIV>
in behavior. I believe the problem is in the marshalling =
attributes, but
</DIV>
<DIV>
I have yet to discover how to examine the memory in mono on linux.
</DIV>
<DIV>
Installing/configuring a windows client and running/debugging there
</DIV>
<DIV>
may be the easiest path.
</DIV>
<DIV> </DIV>
<DIV>
Thanks again for the help.
</DIV>
<DIV>
Jim
</DIV>
<DIV> </DIV>
<DIV>
// interop struct
</DIV>
<DIV>
[ StructLayout(LayoutKind.Sequential) ]
</DIV>
<DIV>
private�unsafe�struct�InternalPrinterList
</DIV>
<DIV>
{
</DIV>
<DIV>
[MarshalAs(UnmanagedType.ByValTStr/*LPStr*/, =
SizeConst=3D1024)]
</DIV>
<DIV>
public string printerUri;
</DIV>
<DIV> </DIV>
<DIV>
[MarshalAs(UnmanagedType.ByValTStr/*LPStr*/, =
SizeConst=3D1024)]
</DIV>
<DIV>
public string printerCupsUri;
</DIV>
<DIV> </DIV>
<DIV>
[MarshalAs(UnmanagedType.ByValTStr/*LPStr*/, =
SizeConst=3D1024)]
</DIV>
<DIV>
public string printerName;
</DIV>
<DIV> </DIV>
<DIV>
[MarshalAs(UnmanagedType.ByValTStr/*LPStr*/,SizeCon=
st=3D81)]
</DIV>
<DIV>
public�string�printerMakeModel;
</DIV>
<DIV> </DIV>
<DIV>
[MarshalAs(UnmanagedType.U4)]
</DIV>
<DIV>
public InternalPrinterList *nextElement;
</DIV>
<DIV>
}
</DIV>
<DIV> </DIV>
<DIV>
// Convert linked list constructed by unmanaged code to
</DIV>
<DIV>
// array of user-visible PrinterList objects.
</DIV>
<DIV>
public static unsafe PrinterList[] ListLocalPrinters()
</DIV>
<DIV>
{
</DIV>
<DIV>
IntPtr list =3D IntPtr.Zero;
</DIV>
<DIV>
try
</DIV>
<DIV>
{
</DIV>
<DIV>
ListLocalPrinters(ref list);
</DIV>
<DIV>
InternalPrinterList* printer =3D =
(InternalPrinterList *)list;
</DIV>
<DIV>
ArrayList printers =3D new =
ArrayList();
</DIV>
<DIV>
while (printer !=3D null)
</DIV>
<DIV>
{
</DIV>
<DIV>
PrinterList pl =
=3D new PrinterList();
</DIV>
<DIV>
pl.Uri =3D =
printer->printerUri;
</DIV>
<DIV>
pl.CupsUri =3D =
printer->printerCupsUri;
</DIV>
<DIV>
pl.Name =3D =
printer->printerName;
</DIV>
<DIV>
pl.MakeModel =
=3D printer->printerMakeModel;
</DIV>
<DIV>
// throws =
NullReferenceException=20
</DIV>
<DIV>
Console.WriteLi=
ne("PrinterInfo: {0}, {1}", pl.Name, pl.Uri);
</DIV>
<DIV> </DIV>
<DIV>
printers.Add(pl=
);
</DIV>
<DIV>
// Something =
not right here as we will go through again
</DIV>
<DIV>
// even when =
list contains only 1 element.
</DIV>
<DIV>
printer =3D =
printer->nextElement;
</DIV>
<DIV>
}
</DIV>
<DIV>
PrinterList[] rval =3D new =
PrinterList[printers.Count];
</DIV>
<DIV>
printers.CopyTo(rval);
</DIV>
<DIV>
return rval;
</DIV>
<DIV>
}
</DIV>
<DIV>
catch (Exception e)
</DIV>
<DIV>
{
</DIV>
<DIV>
return new PrinterList[0];
</DIV>
<DIV>
}
</DIV>
<DIV>
finally
</DIV>
<DIV>
{
</DIV>
<DIV>
if (list !=3D IntPtr.Zero)
</DIV>
<DIV>
FreeLocalPrinte=
rList(list);
</DIV>
<DIV>
}
</DIV>
<DIV>
}
</DIV>
</body>
</html>
--=__Part6F4F1C04.0__=--