RE: [Python.NET] Problem whith DirectX device creation under pythonnet
[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@zope.com V.P. Engineering 540.361.1716 Zope Corporation http://www.zope.com
-----Original Message----- From: Laurent Caumont [mailto:lcaumont@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@pamdev.com> To: "Laurent Caumont" <lcaumont@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@pamdev.com> To: "Brian Lloyd" <brian@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@zope.com> To: "Laurent Caumont" <lcaumont@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@zope.com V.P. Engineering 540.361.1716 Zope Corporation http://www.zope.com
-----Original Message----- From: Laurent Caumont [mailto:lcaumont@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@zope.com> To: "Laurent Caumont" <lcaumont@pamdev.com>; <pythondotnet@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@zope.com V.P. Engineering 540.361.1716 Zope Corporation http://www.zope.com
"from CLR.Microsoft.DirectX.Direct3D import Mesh" => ImportError: cannot import name Mesh It seems that 'Mesh' is define in the Direct3DX library because when I remove the reference the "Microsoft.DirectX.Direct3DX" in the reference list in a directx C# sample, I have the same error... How can I add a refrence like in C# ? The "import CLR.Microsoft.DirectX.Direct3DX as D3DX" doesn't work. Thanks for help.
"from CLR.Microsoft.DirectX.Direct3D import Mesh"
=> ImportError: cannot import name Mesh
It seems that 'Mesh' is define in the Direct3DX library because when I remove the reference the "Microsoft.DirectX.Direct3DX" in the reference list in a directx C# sample, I have the same error...
How can I add a refrence like in C# ?
The "import CLR.Microsoft.DirectX.Direct3DX as D3DX" doesn't work.
Thanks for help.
What is the actual name of the _assembly_ that implements the Direct3DX library? Remember that the name-based import in Python is linked to namespaces, and 'implicit assembly loading' only happens if the namespace you are trying to import happens to match the name of the assembly implementing it (which luckily is often, but not always, the case). So for example, if the assembly is actually named 'Direct3DX.dll', you'll need to load the assembly explicitly before attempting to import the namespace, since the names don't match. There is an example of this in the README for Python for .NET: from CLR.System.Reflection import Assembly a = Assembly.LoadWithPartialName("SomeAssembly") # now we can import namespaces defined in that assembly from CLR.SomeNamespace import Something Brian Lloyd brian@zope.com V.P. Engineering 540.361.1716 Zope Corporation http://www.zope.com
It seem that Mesh is in NameSpace 'CLR.Microsoft.DirectX.Direct3D' but is define in the DLL : Microsoft.DirectX.Direct3DX.dll so I try that: a = Assembly.LoadWithPartialName("C:\...\Microsoft.DirectX.Direct3DX.dll") from CLR.Microsoft.DirectX.Direct3D import Mesh But doesn't work. If i well understand, 'from CLR.Microsoft.DirectX.Direct3D import Mesh' try to import 'Mesh' from CLR.Microsoft.DirectX.Direct3D.dll not CLR.Microsoft.DirectX.Direct3DX.dll , isn't it ? The both dll share the same NameSpace. ----- Original Message ----- From: "Brian Lloyd" <brian@zope.com> To: "Laurent Caumont" <lcaumont@pamdev.com> Cc: <pythondotnet@python.org> Sent: Thursday, January 22, 2004 4:02 PM Subject: RE: Problem whith DirectX Mesh importation
"from CLR.Microsoft.DirectX.Direct3D import Mesh"
=> ImportError: cannot import name Mesh
It seems that 'Mesh' is define in the Direct3DX library because when I remove the reference the "Microsoft.DirectX.Direct3DX" in the reference list in a directx C# sample, I have the same error...
How can I add a refrence like in C# ?
The "import CLR.Microsoft.DirectX.Direct3DX as D3DX" doesn't work.
Thanks for help.
What is the actual name of the _assembly_ that implements the Direct3DX library?
Remember that the name-based import in Python is linked to namespaces, and 'implicit assembly loading' only happens if the namespace you are trying to import happens to match the name of the assembly implementing it (which luckily is often, but not always, the case).
So for example, if the assembly is actually named 'Direct3DX.dll', you'll need to load the assembly explicitly before attempting to import the namespace, since the names don't match. There is an example of this in the README for Python for .NET:
from CLR.System.Reflection import Assembly
a = Assembly.LoadWithPartialName("SomeAssembly")
# now we can import namespaces defined in that assembly
from CLR.SomeNamespace import Something
Brian Lloyd brian@zope.com V.P. Engineering 540.361.1716 Zope Corporation http://www.zope.com
It seem that Mesh is in NameSpace 'CLR.Microsoft.DirectX.Direct3D' but is define in the DLL : Microsoft.DirectX.Direct3DX.dll
so I try that: a = Assembly.LoadWithPartialName("C:\...\Microsoft.DirectX.Direct3DX.dll") from CLR.Microsoft.DirectX.Direct3D import Mesh
But doesn't work.
I don't think that LoadWithPartialName wants a path. Try: Assembly.LoadWithPartialName('Microsoft.DirectX.Direct3DX')
If i well understand, 'from CLR.Microsoft.DirectX.Direct3D import Mesh' try to import 'Mesh' from CLR.Microsoft.DirectX.Direct3D.dll not CLR.Microsoft.DirectX.Direct3DX.dll , isn't it ?
The both dll share the same NameSpace.
That shouldn't be a problem. The Python runtime can find objects in different dlls that all live in the same namespace. The key is making sure that you get the assembly loaded before trying to do the import. Brian Lloyd brian@zope.com V.P. Engineering 540.361.1716 Zope Corporation http://www.zope.com
Yes, you are Right ! That's work very well ! Thank you for all. :) ----- Original Message ----- From: "Brian Lloyd" <brian@zope.com> To: "Laurent Caumont" <lcaumont@pamdev.com> Cc: <pythondotnet@python.org> Sent: Thursday, January 22, 2004 5:13 PM Subject: RE: Problem whith DirectX Mesh importation
It seem that Mesh is in NameSpace 'CLR.Microsoft.DirectX.Direct3D' but is define in the DLL : Microsoft.DirectX.Direct3DX.dll
so I try that: a = Assembly.LoadWithPartialName("C:\...\Microsoft.DirectX.Direct3DX.dll") from CLR.Microsoft.DirectX.Direct3D import Mesh
But doesn't work.
I don't think that LoadWithPartialName wants a path. Try:
Assembly.LoadWithPartialName('Microsoft.DirectX.Direct3DX')
If i well understand, 'from CLR.Microsoft.DirectX.Direct3D import Mesh' try to import 'Mesh' from CLR.Microsoft.DirectX.Direct3D.dll not CLR.Microsoft.DirectX.Direct3DX.dll , isn't it ?
The both dll share the same NameSpace.
That shouldn't be a problem. The Python runtime can find objects in different dlls that all live in the same namespace. The key is making sure that you get the assembly loaded before trying to do the import.
Brian Lloyd brian@zope.com V.P. Engineering 540.361.1716 Zope Corporation http://www.zope.com
participants (2)
-
Brian Lloyd
-
Laurent Caumont