Thanks Dino, the ctypes.memmove does work! I wasn't aware that ctypes could be used in IronPython. Do they marshal to unmanaged code under the hood?
Let me know if you want me to file a bug against the Marshal.Copy overload behavior. Thanks, -- Marcel On Jun 15, 11:42 am, Dino Viehland <[email protected]> wrote: > Can I make a different recommendation? Rather than doing a Marshal.Copy > you could use ctypes.memmove. That would look like: > > import ctypes > ctypes.memmove(bmData.Scan0, bytes.buffer_info()[0], total_bytes) > > If Scan0 is actually an IntPtr youa may need to do a .ToInt32() or .ToInt64() > on it (I don't remember if we support IntPtr's when marshalling to ctypes - > we probably should). > > Even better still would be to use a ctypes array: > > bytes_type = (ctypes.c_int8* total_bytes) > bytes = bytes_type() > ctypes.memmove(0, bytes, total_bytes) > > > > > -----Original Message----- > > From: [email protected] [mailto:users- > > [email protected]] On Behalf Of Marcel > > Sent: Monday, June 14, 2010 6:21 PM > > To: [email protected] > > Subject: Re: [IronPython] Convert between python array and .NET Array > > > Hi Curt, > > > I did try that overload but I get this quite amusing error message: > > TypeError: Copy() takes at least 2147483647 arguments (4 given) > > > Without the explicit overload selection, I get: > > TypeError: expected IntPtr, got int > > > Did the example work for you with the overload you suggested? > > > The reason I chose array('B') was twofold. The pixel generation is > > done in a pure Python library and I sometimes need to swap the byes > > (depending on the endianness of the system), which the Python array > > conveniently provides. > > > Thanks, > > -- Marcel > > > On Jun 14, 7:05 am, Curt Hagenlocher <[email protected]> wrote: > > > Ah, I'm clearly not familiar with how the array type was implemented. The > > > first member of the buffer_info() tuple is an IntPtr, so you probably want > > > the [IntPtr, int, IntPtr, int] overload of Marshal.Copy. In fact, if you > > > use > > > the buffer_info() approach, you may be able to avoid manually specifying > > > the > > > overload. (Though there's something to be said for the types as a form of > > > documentation -- particularly given the opacity of the call to > > > buffer_info()). > > > > Personally, my rule of thumb is to use the Python standard library for > > > portable and "mostly Pythonic" code, but to use .NET types when doing > > > "mostly .NET". In this case, I think I would have created an Array[Byte] > > > instead of an array('B') as it's a bit more self-documenting. > > > > On Sun, Jun 13, 2010 at 3:51 PM, Marcel > > <[email protected]>wrote: > > > > > Hi Curt, > > > > > Your suggestion gives me: > > > > TypeError: expected Array[Byte], got array > > > > > bytes is a Python array. I tried: > > > > Marshal.Copy.Overloads[Array[Byte], int, IntPtr, int] > > > > (bytes.buffer_info()[0], 0, bmData.Scan0, total_bytes) > > > > > but that gave the error: > > > > TypeError: expected Array[Byte], got int > > > > > This small sample application demonstrates the issue: > > > > > import array > > > > import struct > > > > import StringIO > > > > > import clr > > > > clr.AddReference("System.Windows.Forms") > > > > clr.AddReference("System.Drawing") > > > > > from System import Array, Byte, Char, IntPtr > > > > from System.Windows.Forms import Application, Form, PictureBox > > > > from System.Drawing import Size, Point, Bitmap, Color, Rectangle > > > > from System.Drawing.Imaging import PixelFormat, ImageLockMode > > > > from System.Runtime.InteropServices import Marshal > > > > > class IForm(Form): > > > > > def __init__(self): > > > > bytes = array.array('B') > > > > > width = 25 > > > > height = 20 > > > > > for i in range(width * height): > > > > bytes.append(i % 256) # R > > > > bytes.append(i % 256) # G > > > > bytes.append(i % 256) # B > > > > > bitmap = Bitmap(width, height, PixelFormat.Format24bppRgb) > > > > > bmData = bitmap.LockBits(Rectangle(0, 0, bitmap.Width, > > > > bitmap.Height), > > > > ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb) > > > > > total_bytes = (bmData.Stride) * bmData.Height > > > > > Marshal.Copy.Overloads[Array[Byte], int, IntPtr, int]( > > > > bytes.buffer_info()[0], 0, bmData.Scan0, total_bytes) > > > > bitmap.UnlockBits(bmData) > > > > > ## for x in range(width): > > > > ## for y in range(height): > > > > ## i = y * width + x > > > > ## bitmap.SetPixel(x, y, Color.FromArgb(bytes[i], > > > > bytes[i+1], bytes[i+2])) > > > > > pb = PictureBox() > > > > pb.Size = Size(bitmap.Width, bitmap.Height) > > > > pb.Location = Point(2, 2) > > > > pb.Image = bitmap > > > > pb.Parent = self > > > > > self.Size = Size(bitmap.Width + 20, bitmap.Height + 45) > > > > self.CenterToScreen() > > > > > Application.Run(IForm()) > > > > > Using bitmap.SetPixel works, but I cannot find how to make it work > > > > using the LockBits and Marshal.Copy. > > > > > Thanks, > > > > -- Marcel > > > > > On Jun 12, 10:27 pm, Curt Hagenlocher <[email protected]> wrote: > > > > > It looks like the automatic overload resolution may be failing -- at > > > > least, > > > > > it's worth trying to resolve the overload manually. This would be > > > > something > > > > > like > > > > > > from System import Array, Byte, IntPtr > > > > > Marshal.Copy.Overloads[Array[Byte], int, IntPtr, int](bytes, 0, > > > > > bmData.Scan0, total_bytes) > > > > > > On Sat, Jun 12, 2010 at 10:07 PM, Marcel > > > > > <[email protected] > > > > >wrote: > > > > > > > I think I simplified my example a little too far. I'm trying to > > > > > > display a Bitmap from bytes generated in Python code. > > > > > > > bytes = array.array('c') # tried 'B' also > > > > > > # generate bitmap bytes ... > > > > > > > bitmap = Bitmap(width, height, PixelFormat.Format24bppRgb) > > > > > > > bmData = bitmap.LockBits(Rectangle(0, 0, bitmap.Width, > > > > > > bitmap.Height), > > > > > > ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb) > > > > > > > total_bytes = (bmData.Stride) * bmData.Height > > > > > > > Marshal.Copy(bytes, 0, bmData.Scan0, total_bytes); > > > > > > > bitmap.UnlockBits(bmData) > > > > > > > The IronPython exception I'm getting is: > > > > > > TypeError: expected IntPtr, got array > > > > > > > Casting the bytes array to IntPtr changed the error into: > > > > > > TypeError: expected int, got array > > > > > > > I'm using IronPython 2.6 (2.6.10920.0) on .NET 2.0.50727.4927 > > > > > > > Any idea? > > > > > > > Thanks, > > > > > > -- Marcel > > > > > > > On Jun 11, 11:27 pm, David Escobar <[email protected]> wrote: > > > > > > > This worked for me (based on the code you provided): > > > > > > > > import clr > > > > > > > from System import Array > > > > > > > > dest = Array[str](bytes) > > > > > > > > On Fri, Jun 11, 2010 at 9:51 PM, Marcel < > > > > [email protected] > > > > > > >wrote: > > > > > > > > > I have a python method that returns a Python byte > > array.array('c'). > > > > > > > > > Now, I want to copy this array using > > > > > > > > System.Runtime.InteropServices.Marshal.Copy. This method however > > > > > > > > expects a .NET Array. > > > > > > > > > import array > > > > > > > > from System.Runtime.InteropServices import Marshal > > > > > > > > > bytes = array.array('c') > > > > > > > > bytes.append('a') > > > > > > > > bytes.append('b') > > > > > > > > bytes.append('c') > > > > > > > > Marshal.Copy(bytes, dest, 0, 3) > > > > > > > > > Is there a way to make this work without copying the data? If > > > > > > > > not, > > > > how > > > > > > > > do I convert the data in the Python array to the .NET array? > > > > > > > > > Thanks, > > > > > > > > -- Marcel > > > > > > > > _______________________________________________ > > > > > > > > Users mailing list > > > > > > > > [email protected] > > > > > > > >http://lists.ironpython.com/listinfo.cgi/users-ironpython.com > > > > > > > > _______________________________________________ > > > > > > > Users mailing list > > > > > > > [email protected]:// > > > > > > lists.ironpython.com/listinfo.cgi/users-ironpython.com > > > > > > _______________________________________________ > > > > > > Users mailing list > > > > > > [email protected] > > > > > >http://lists.ironpython.com/listinfo.cgi/users-ironpython.com > > > > > > _______________________________________________ > > > > > Users mailing list > > > > > [email protected]:// > > > > lists.ironpython.com/listinfo.cgi/users-ironpython.com > > > > _______________________________________________ > > > > Users mailing list > > > > [email protected] > > > >http://lists.ironpython.com/listinfo.cgi/users-ironpython.com > > > > _______________________________________________ > > > Users mailing list > > > [email protected]http://lists.ironpython.com/listinfo.cgi/users- > > ironpython.com > > _______________________________________________ > > Users mailing list > > [email protected] > >http://lists.ironpython.com/listinfo.cgi/users-ironpython.com > > _______________________________________________ > Users mailing list > [email protected]http://lists.ironpython.com/listinfo.cgi/users-ironpython.com _______________________________________________ Users mailing list [email protected] http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
