From brandon at rhodesmill.org Fri May 28 06:10:01 2010 From: brandon at rhodesmill.org (Brandon Craig Rhodes) Date: Fri, 28 May 2010 00:10:01 -0400 Subject: [Python.NET] how can I build an assembly I can AddReference()? Message-ID: <87fx1cll9i.fsf@rhodesmill.org> I am interested in whether Python for .NET can help me provide third-party programmers with a way to write C# routines that will get called from my Python application. I was impressed earlier today with how easily Python for .NET compiled for Python 2.6 and the most recent Visual Studio release, so I set about trying to write a C# routine and call it from inside of Python. I have only gotten as far as trying to AddReference() my new DLL, but have not been able to get it to succeed. I first created a "Brandon.cs" file with this inside: ---------------------------------------- using System; using System.Reflection; [assembly:AssemblyVersion("1.0.0.0")] [assembly:AssemblyDescription("The Brandon library")] [assembly:AssemblyCompany("Rhodes Mill Studios, Inc.")] namespace Brandon { public static class BrandonClass { public static void Go() { Console.WriteLine("Hello, World!"); } } } ---------------------------------------- This was simple enough to compile with: csc /t:library Brandon.cs which produced a "Brandon.dll" file. Look at what happens if I then try importing that DLL from Python for .NET: >>> import clr >>> print clr.FindAssembly('Brandon') C:\Users\brandon\dev\pythonnet\Brandon.dll >>> clr.AddReference('Brandon') ... System.IO.FileNotFoundException: Unable to find assembly 'Brandon'. at Python.Runtime.CLRModule.AddReference(String name) in c:\Users\brandon\dev\pythonnet\src\runtime\moduleobject.cs:line 370 You can see that, oddly enough, Python can find the assembly, but cannot create a reference to it. This error message also results, by the way, if I compile "Brandon.cs" with a "/keyfile:..." option and run "gacutil /i Brandon.dll" before trying to run my Python code. I know that the step I am missing is probably blazingly obvious to those who have been using Windows longer, :-) but I will very much appreciate whomever who can point out what critical step I am missing in getting my Python code to call C# code. Other than this hangup, I'm impressed by how quickly Python for .NET got me up and running! -- Brandon Craig Rhodes brandon at rhodesmill.org http://rhodesmill.org/brandon From dave.hirschfeld at gmail.com Fri May 28 09:52:14 2010 From: dave.hirschfeld at gmail.com (Dave Hirschfeld) Date: Fri, 28 May 2010 07:52:14 +0000 (UTC) Subject: [Python.NET] how can I build an assembly I can AddReference()? References: <87fx1cll9i.fsf@rhodesmill.org> Message-ID: Brandon Craig Rhodes writes: > I have only gotten as far as trying to AddReference() my new DLL, but > have not been able to get it to succeed. > > >>> import clr > >>> print clr.FindAssembly('Brandon') > C:\Users\brandon\dev\pythonnet\Brandon.dll > >>> clr.AddReference('Brandon') > ... > System.IO.FileNotFoundException: Unable to find assembly 'Brandon'. > at Python.Runtime.CLRModule.AddReference(String name) in > c:\Users\brandon\dev\pythonnet\src\runtime\moduleobject.cs:line 370 > > You can see that, oddly enough, Python can find the assembly, but cannot > create a reference to it. Works for me: Python 2.5.4 (r254:67916, Dec 23 2008, 15:10:54) [MSC v.1310 32 bit (Intel)] Type "copyright", "credits" or "license" for more information. IPython 0.10 -- An enhanced Interactive Python. ? -> Introduction and overview of IPython's features. %quickref -> Quick reference. help -> Python's own help system. object? -> Details about 'object'. ?object also works, ?? prints more. In [2]: pwd Out[2]: 'C:\\temp\\PythonDotNET' In [3]: ls Volume in drive C has no label. Volume Serial Number is 90C1-4729 Directory of C:\temp\PythonDotNET 28/05/2010 08:35 . 28/05/2010 08:35 .. 26/10/2009 14:03 5,632 FactoryPattern.dll 1 File(s) 5,632 bytes 2 Dir(s) 188,252,098,560 bytes free In [4]: import clr In [5]: clr.AddReference('FactoryPattern') Out[5]: ...but I was in the same directory as the dll. Are you in the same directory? What happens if you try to put the full path? e.g. clr.AddReference(r'C:\temp\PythonDotNET\FactoryPattern') If that doesn't work does using Assembly.LoadFile work? e.g. from clr import System from System import Reflection full_filename = r'C:\temp\PythonDotNET\FactoryPattern.dll' Reflection.Assembly.LoadFile(full_filename) HTH, Dave From brandon at rhodesmill.org Fri May 28 15:07:08 2010 From: brandon at rhodesmill.org (Brandon Craig Rhodes) Date: Fri, 28 May 2010 09:07:08 -0400 Subject: [Python.NET] how can I build an assembly I can AddReference()? In-Reply-To: (Dave Hirschfeld's message of "Fri, 28 May 2010 07:52:14 +0000 (UTC)") References: <87fx1cll9i.fsf@rhodesmill.org> Message-ID: <87typsjhtv.fsf@rhodesmill.org> Dave Hirschfeld writes: > Brandon Craig Rhodes writes: > >> >>> import clr >> >>> print clr.FindAssembly('Brandon') >> C:\Users\brandon\dev\pythonnet\Brandon.dll >> >>> clr.AddReference('Brandon') >> ... >> System.IO.FileNotFoundException: Unable to find assembly 'Brandon'. >> at Python.Runtime.CLRModule.AddReference(String name) in >> c:\Users\brandon\dev\pythonnet\src\runtime\moduleobject.cs:line 370 > > Works for me ... but I was in the same directory as the dll. Are you > in the same directory? Yes, I am in the same directory; and I just double-checked before replying. :-) > If that doesn't work does using Assembly.LoadFile work? e.g. > > from clr import System > from System import Reflection > full_filename = r'C:\temp\PythonDotNET\FactoryPattern.dll' > Reflection.Assembly.LoadFile(full_filename) Ah! That gives a much more informative error message: Traceback (most recent call last): File "test.py", line 28, in Reflection.Assembly.LoadFile(r'C:\Users\brandon\dev\pythonnet\Brandon.dll') System.BadImageFormatException: This assembly is built by a runtime newer than t he currently loaded runtime and cannot be loaded. (Exception from HRESULT: 0x801 3101B) at System.Reflection.Assembly.nLoadFile(String path, Evidence evidence) at System.Reflection.Assembly.LoadFile(String path) Well, drat. A newer runtime? So in response to this, I have just gone through and removed all traces of earlier Visual Studios and .NET on my computer, leaving only 2010 and 4.0 in my list of installed programs, and then checked out a fresh copy of Python for .NET and rebuilt it with "msbuild" and then tried again. Unfortunately I get the same error message. Is the problem that stock Python 2.6 is built with an older runtime than the one I am using to build my DLL? What should I try next? Thanks for the help! -- Brandon Craig Rhodes brandon at rhodesmill.org http://rhodesmill.org/brandon From brandon at rhodesmill.org Fri May 28 22:36:21 2010 From: brandon at rhodesmill.org (Brandon Craig Rhodes) Date: Fri, 28 May 2010 16:36:21 -0400 Subject: [Python.NET] how can I build an assembly I can AddReference()? In-Reply-To: <87typsjhtv.fsf@rhodesmill.org> (Brandon Craig Rhodes's message of "Fri, 28 May 2010 09:07:08 -0400") References: <87fx1cll9i.fsf@rhodesmill.org> <87typsjhtv.fsf@rhodesmill.org> Message-ID: <87eigvu5kq.fsf@rhodesmill.org> Brandon Craig Rhodes writes: > System.BadImageFormatException: This assembly is built by a runtime newer than t > he currently loaded runtime and cannot be loaded. (Exception from HRESULT: 0x801 > 3101B) > at System.Reflection.Assembly.nLoadFile(String path, Evidence evidence) > at System.Reflection.Assembly.LoadFile(String path) This afternoon I uninstalled Visual Studio 2010 from my laptop and re-installed Visual Studio 2008, then rebuilt "Brandon.dll", in the hopes that 2010 was simply too recent a version of Studio to be using with the c:\python26 from the python.org page. Sadly, I was wrong; I still get the above error when trying to import the DLL. -- Brandon Craig Rhodes brandon at rhodesmill.org http://rhodesmill.org/brandon From brandon at rhodesmill.org Fri May 28 22:52:15 2010 From: brandon at rhodesmill.org (Brandon Craig Rhodes) Date: Fri, 28 May 2010 16:52:15 -0400 Subject: [Python.NET] how can I build an assembly I can AddReference()? In-Reply-To: <87typsjhtv.fsf@rhodesmill.org> (Brandon Craig Rhodes's message of "Fri, 28 May 2010 09:07:08 -0400") References: <87fx1cll9i.fsf@rhodesmill.org> <87typsjhtv.fsf@rhodesmill.org> Message-ID: <878w73u4u8.fsf@rhodesmill.org> Aha! I can now build my assembly successfully and import it into Python! Upon closer inspection, I discovered that uninstalling Visual Studio 2010 did *not* actually remove the compilation subsystem I was using, it turns out, from C:\Windows\Microsoft.NET\Framework\v4.0.30319. And so my DLL was still coming out based on a too-recent runtime version. Once I replaced my %PATH% with: PATH=C:\Windows\Microsoft.NET\Framework\v3.5 and re-ran "csc /t:library Brandon.cs", I got a DLL that imports and runs just fine from inside of Python! So it was just my ignorance of how Windows development works, and of which paths and installed components determine the runtime version of a built component, that seems to have caused the problem. This experience over the last two days - of, in effect, staring at a bank of knobs and blinking lights and having no idea which knobs will have what effects - really helped me have sympathy as I was simultaneously answering some questions from a friend who is trying to figure out how to compile Python on a Mac when he has never dealt with "configure", "make", or shared libraries before. It made it easier to remember that what seemed so sensible and obvious to me was a complete blank wall of ignorance and mystery to him. :-) -- Brandon Craig Rhodes brandon at rhodesmill.org http://rhodesmill.org/brandon