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: users-boun...@lists.ironpython.com [mailto:users- > boun...@lists.ironpython.com] On Behalf Of Marcel > Sent: Monday, June 14, 2010 6:21 PM > To: users@lists.ironpython.com > 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 <c...@hagenlocher.org> 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 > <marcel.vandendun...@gmail.com>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 <c...@hagenlocher.org> 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 <marcel.vandendun...@gmail.com > > > >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 <davidesco...@ieee.org> 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 < > > > marcel.vandendun...@gmail.com > > > > > >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 > > > > > > > us...@lists.ironpython.com > > > > > > >http://lists.ironpython.com/listinfo.cgi/users-ironpython.com > > > > > > > > _______________________________________________ > > > > > > Users mailing list > > > > > > us...@lists.ironpython.comhttp:// > > > > > lists.ironpython.com/listinfo.cgi/users-ironpython.com > > > > > _______________________________________________ > > > > > Users mailing list > > > > > us...@lists.ironpython.com > > > > >http://lists.ironpython.com/listinfo.cgi/users-ironpython.com > > > > > > _______________________________________________ > > > > Users mailing list > > > > us...@lists.ironpython.comhttp:// > > > lists.ironpython.com/listinfo.cgi/users-ironpython.com > > > _______________________________________________ > > > Users mailing list > > > us...@lists.ironpython.com > > >http://lists.ironpython.com/listinfo.cgi/users-ironpython.com > > > > > > > > _______________________________________________ > > Users mailing list > > us...@lists.ironpython.comhttp://lists.ironpython.com/listinfo.cgi/users- > ironpython.com > _______________________________________________ > Users mailing list > Users@lists.ironpython.com > http://lists.ironpython.com/listinfo.cgi/users-ironpython.com _______________________________________________ Users mailing list Users@lists.ironpython.com http://lists.ironpython.com/listinfo.cgi/users-ironpython.com