[IronPython] Convert between python array and .NET Array

Marcel marcel.vandendungen at gmail.com
Mon Jun 14 00:51:07 CEST 2010


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... at 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... at 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... at 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... at 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... at lists.ironpython.com
> > > >http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
>
> > > _______________________________________________
> > > Users mailing list
> > > Us... at lists.ironpython.comhttp://
> > lists.ironpython.com/listinfo.cgi/users-ironpython.com
> > _______________________________________________
> > Users mailing list
> > Us... at lists.ironpython.com
> >http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
>
>
>
> _______________________________________________
> Users mailing list
> Us... at lists.ironpython.comhttp://lists.ironpython.com/listinfo.cgi/users-ironpython.com



More information about the Ironpython-users mailing list