[Python.NET] Problem whith DirectX device creation under pythonnet

Brian Lloyd brian at zope.com
Fri Jan 16 13:39:27 EST 2004


[Copying the list on this as well, as it is probably relevant to
 everyone sooner or later...]

Looking at this, I see what the issue is but I'm not sure how
to address it, other than by documentation.

The problem is the distinction between value types and reference
types and how that distinction affects you when writing in Python.

To take a boiled-down version of your example:

  items = CLR.System.Array.CreateInstance(Point, 3)
  for i in range(3):
    items[i] = Point(0, 0)

  items[0].X = 1 # won't work!!

While the spelling of 'items[0].X = 1' is the same in C# and Python,
there is an important and subtle semantic difference. In C# (and other
compiled-to-IL languages), the compiler knows that Point is a value
type and can do the Right Thing here, changing the value in place.

In Python however, "everything's a reference", and there is really no
spelling or semantic to allow it to do the right thing dynamically. The
specific reason that items[0] itself doesn't change is that when you
say 'items[0]', that getitem operation creates a Python object that
holds a reference to the object at items[0] via a GCHandle. That causes
a ValueType (like Point) to be boxed, so the following setattr ('.X = 1')
*changes the state of the boxed value, not the original unboxed value*.

Because there are no value type semantics or syntax in Python, there's
not much the runtime can do about this :( The workaround is to do what
you did, which is to make all of your changes to the boxed copy and then
set (or re-set) the item in the array.

This is not unlike some of the cases you can find in C# where you have
to know about boxing behavior to avoid similar kinds of 'lost update'
problems (generally because an implicit boxing happened that was not
taken into account in the code).

This is the same thing, just the manifestation is a little different
in Python. The rule in Python is essentially: "the result of any
attribute or item access is a boxed value", and as your example shows
that can be important in how you approach your code.

I've added a TODO to put a section about this into the docs - I'm sure
it will be a FAQ.


Brian Lloyd        brian at zope.com
V.P. Engineering   540.361.1716
Zope Corporation   http://www.zope.com


> -----Original Message-----
> From: Laurent Caumont [mailto:lcaumont at pamdev.com]
> Sent: Thursday, January 15, 2004 8:40 AM
> To: Brian Lloyd
> Subject: Re: [Python.NET] Problem whith DirectX device creation under
> pythonnet
>
>
> I have found a solution:
>
>         self.vertexBuffer =
> VertexBuffer(CustomVertex.TransformedColored, 3,
> self.device, 0, CustomVertex.TransformedColored.Format, Pool.Default)
>         stm = self.vertexBuffer.Lock(0, 0, 0)
>         verts =
> System.Array.CreateInstance(CustomVertex.TransformedColored,
> 3)
>
>         verts[0] = CustomVertex.TransformedColored(150, 50, 0.5, 1.0,
> System.Drawing.Color.Aqua.ToArgb())
> ##        verts[0].X = 150.0
> ##        verts[0].Y = 50
> ##        verts[0].Z = 0.5
> ##        verts[0].Rhw = 1.0
> ##        verts[0].Color = System.Drawing.Color.Aqua.ToArgb()
>         verts[1] = CustomVertex.TransformedColored(250, 250, 0.5, 1.0,
> System.Drawing.Color.Brown.ToArgb())
> ##        verts[1].X = 250
> ##        verts[1].Y = 250
> ##        verts[1].Z = 0.5
> ##        verts[1].Rhw = 1.0
> ##        verts[1].Color = System.Drawing.Color.Brown.ToArgb()
>         verts[2] = CustomVertex.TransformedColored(50, 250, 0.5, 1.0,
> System.Drawing.Color.LightPink.ToArgb())
> ##        verts[2].X = 50
> ##        verts[2].Y = 250
> ##        verts[2].Z = 0.5
> ##        verts[2].Rhw = 1.0
> ##        verts[2].Color = System.Drawing.Color.LightPink.ToArgb()
>
>         stm.Write(verts)
>         self.vertexBuffer.Unlock()
>
>
> I don't know why but the comment lines do not work: the values are not
> changed. ( print verts[0].X = 0.0 ??)
>
> ----- Original Message -----
> From: "Laurent Caumont" <lcaumont at pamdev.com>
> To: "Laurent Caumont" <lcaumont at pamdev.com>
> Sent: Thursday, January 15, 2004 2:39 PM
> Subject: Re: [Python.NET] Problem whith DirectX device creation under
> pythonnet
>
>
> > I have found a solution:
> >
> >         self.vertexBuffer =
> VertexBuffer(CustomVertex.TransformedColored,
> 3,
> > self.device, 0, CustomVertex.TransformedColored.Format, Pool.Default)
> >         stm = self.vertexBuffer.Lock(0, 0, 0)
> >         verts =
> System.Array.CreateInstance(CustomVertex.TransformedColored,
> > 3)
> >
> >         verts[0] = CustomVertex.TransformedColored(150, 50, 0.5, 1.0,
> > System.Drawing.Color.Aqua.ToArgb())
> > ##        verts[0].X = 150.0
> > ##        verts[0].Y = 50
> > ##        verts[0].Z = 0.5
> > ##        verts[0].Rhw = 1.0
> > ##        verts[0].Color = System.Drawing.Color.Aqua.ToArgb()
> >         verts[1] = CustomVertex.TransformedColored(250, 250, 0.5, 1.0,
> > System.Drawing.Color.Brown.ToArgb())
> > ##        verts[1].X = 250
> > ##        verts[1].Y = 250
> > ##        verts[1].Z = 0.5
> > ##        verts[1].Rhw = 1.0
> > ##        verts[1].Color = System.Drawing.Color.Brown.ToArgb()
> >         verts[2] = CustomVertex.TransformedColored(50, 250, 0.5, 1.0,
> > System.Drawing.Color.LightPink.ToArgb())
> > ##        verts[2].X = 50
> > ##        verts[2].Y = 250
> > ##        verts[2].Z = 0.5
> > ##        verts[2].Rhw = 1.0
> > ##        verts[2].Color = System.Drawing.Color.LightPink.ToArgb()
> >
> >         stm.Write(verts)
> >         self.vertexBuffer.Unlock()
> >
> >
> > I don't know why but the comment lines do not work: the values are not
> > changed. ( print verts[0].X = 0.0 ??)
> >
> >
> >
> > ----- Original Message -----
> > From: "Laurent Caumont" <lcaumont at pamdev.com>
> > To: "Brian Lloyd" <brian at zope.com>
> > Sent: Thursday, January 15, 2004 12:45 PM
> > Subject: Re: [Python.NET] Problem whith DirectX device creation under
> > pythonnet
> >
> >
> > > YES. It works for me too !
> > >
> > > I am very surprise that DirectX Documentation doesn't say
> that it is an
> > > array.
> > >
> > > About arrays, I have a question:
> > > I try to convert this C# code to PythonNet like this:
> > >
> > > C#:
> > >
> > > vertexBuffer = new
> VertexBuffer(typeof(CustomVertex.TransformedColored),
> > 3,
> > > dev, 0, CustomVertex.TransformedColored.Format, Pool.Default);
> > > GraphicsStream stm = vertexBuffer.Lock(0, 0, 0);
> > > CustomVertex.TransformedColored[] verts = new
> > > CustomVertex.TransformedColored[3];
> > > verts[0].X=150;verts[0].Y=50;verts[0].Z=0.5f; verts[0].Rhw=1;
> > verts[0].Color
> > > = System.Drawing.Color.Aqua.ToArgb();
> > > verts[1].X=250;verts[1].Y=250;verts[1].Z=0.5f; verts[1].Rhw=1;
> > > verts[1].Color = System.Drawing.Color.Brown.ToArgb();
> > > verts[2].X=50;verts[2].Y=250;verts[2].Z=0.5f; verts[2].Rhw=1;
> > verts[2].Color
> > > = System.Drawing.Color.LightPink.ToArgb();
> > > stm.Write(verts);
> > > vertexBuffer.Unlock();
> > >
> > > Python:
> > >
> > > self.vertexBuffer = VertexBuffer(CustomVertex.TransformedColored, 3,
> > > self.device, 0, CustomVertex.TransformedColored.Format, Pool.Default)
> > > stm = self.vertexBuffer.Lock(0, 0, 0)
> > > verts = []
> > > verts.append(CustomVertex.TransformedColored(150, 50, 0.5, 1,
> > > Color.Aqua.ToArgb()))
> > > verts.append(CustomVertex.TransformedColored(250, 250, 0.5, 1,
> > > Color.Brown.ToArgb()))
> > > verts.append(CustomVertex.TransformedColored(50, 250, 0.5, 1,
> > > Color.LightPink.ToArgb()))
> > >
> > > stm.Write(verts)
> > > self.vertexBuffer.Unlock()
> > >
> > >
> > > "stm.Write" doesn't like my verts array. (TypeError: no method matches
> > given
> > > arguments)
> > >
> > > I have remove the 'typeof' too but I don't know if it's ok ?
> > >
> > > Thanks for the Help.
> > >
> > >
> > > ----- Original Message -----
> > > From: "Brian Lloyd" <brian at zope.com>
> > > To: "Laurent Caumont" <lcaumont at pamdev.com>
> > > Sent: Wednesday, January 14, 2004 10:01 PM
> > > Subject: RE: [Python.NET] Problem whith DirectX device creation under
> > > pythonnet
> > >
> > >
> > > > I think I have an answer for you ;) Looking at the sig, the
> > > > 'PresentParams' arg is actually PresentParams[] (iow, array
> > > > of PresentParams rather than one).
> > > >
> > > > When I changed the call to:
> > > >
> > > >   Device(0, DeviceType.Hardware, self,
> > > CreateFlags.SofwareVertexProcessing,
> > > >          [presentParams])
> > > >
> > > > it worked for me.
> > > >
> > > >
> > > > Brian Lloyd        brian at zope.com
> > > > V.P. Engineering   540.361.1716
> > > > Zope Corporation   http://www.zope.com
> > > >
> > > >
> > > > > -----Original Message-----
> > > > > From: Laurent Caumont [mailto:lcaumont at pamdev.com]
> > > > > Sent: Wednesday, January 14, 2004 4:54 AM
> > > > > To: Brian Lloyd
> > > > > Subject: Re: [Python.NET] Problem whith DirectX device creation
> under
> > > > > pythonnet
> > > > >
> > > > >
> > > > > Hi Brian,
> > > > >
> > > > > Yes, I use the b3 release.
> > > > >
> > > > > I suspect the enum to be the cause of the error.
> > > > >
> > > > > If you do that:
> > > > > "dtype = DeviceType.Hardware"
> > > > > dtype is a "int" not a "DeviceType" (enum).
> > > > >
> > > > > But the constructor need a "DeviceType" not a "int".
> > > > >
> > > > > Is it possible with pyton to force the type (cast)?
> > > > >
> > > > > Thanks.
> > > > >
> > > > > ----- Original Message -----
> > > > > From: "Brian Lloyd" <brian at zope.com>
> > > > > To: "Laurent Caumont" <lcaumont at pamdev.com>;
> <pythondotnet at python.org>
> > > > > Sent: Tuesday, January 13, 2004 4:43 PM
> > > > > Subject: RE: [Python.NET] Problem whith DirectX device creation
> under
> > > > > pythonnet
> > > > >
> > > > >
> > > > > > > I use the "DirectX 9.0 SDK Update (Summer 2003)"
> documentation.
> > > > > > >
> > > > > > > This C# sample is very close to my code.
> > > > > > > It use the same constructor.
> > > > > > >
> > > > > > > Is there any way to view the constructor signature
> with python ?
> > > > > > >
> > > > > > > Laurent.
> > > > > >
> > > > > > Not currently, though I've put it on the todo list (I
> think I can
> > > > > > have SomeClass.__doc__ display constructor info).
> > > > > >
> > > > > > Your code _looks_ right, which makes me suspect that the Python
> > > > > > integration layer is somehow mishandling one of the arguments. I
> > > > > > don't have managed directx handy, so I don't have a quick way
> > > > > > to check that theory :(
> > > > > >
> > > > > > If you're inclined, you can probably hack the
> MethodBinder.cs file
> > > > > > to log what it's doing when it tries to convert the arguments.
> I'll
> > > > > > try to get mdx installed to try to reproduce it myself,
> but it may
> > > > > > be a few days.
> > > > > >
> > > > > > Just to be sure - you are using the latest beta, right?
> Beta 2 had
> > > > > > a bug that caused problems calling ctors, so make sure you are
> > > > > > using the b3 release.
> > > > > >
> > > > > >
> > > > > > Brian Lloyd        brian at zope.com
> > > > > > V.P. Engineering   540.361.1716
> > > > > > Zope Corporation   http://www.zope.com
> > > > > >
> > > > > >
> > > > >
> > > > >
> > >
> >
>
>




More information about the PythonDotNet mailing list