how can I build an assembly I can AddReference()?
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@rhodesmill.org http://rhodesmill.org/brandon
Brandon Craig Rhodes <brandon@...> writes:
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 <DIR> . 28/05/2010 08:35 <DIR> .. 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]: <System.Reflection.Assembly object at 0x03798DA0> ...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
Dave Hirschfeld <dave.hirschfeld@gmail.com> writes:
Yes, I am in the same directory; and I just double-checked before replying. :-)
Ah! That gives a much more informative error message: Traceback (most recent call last): File "test.py", line 28, in <module> 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@rhodesmill.org http://rhodesmill.org/brandon
Brandon Craig Rhodes <brandon@rhodesmill.org> writes:
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@rhodesmill.org http://rhodesmill.org/brandon
I needed to access .NET dlls compiled for .NET4 and also ran into the System.BadImageFormatException error. I opened PythonDotNET in VS2010 and it compiled fine with only a couple of errors about System.Security.Permissions.SecurityAction.RequestMinimum being obsolete. Unfortunately when I tried to import clr I got the following error: SystemError: dynamic module not initialized properly Looking further into it I found that in buildclrmodule.bat lines 33 & 66 referenced the .NET2 idalsm.exe: %windir%\Microsoft.NET\Framework\v2.0.50727\ilasm /nologo /quiet /dll %ILASM_EXTRA_ARGS% /include=%INCLUDE_PATH% /output=%OUTPUT_PATH% %INPUT_PATH% I changed this to reference the .NET4 version: %windir%\Microsoft.NET\Framework\v4.0.30319\ilasm /nologo /quiet /dll %ILASM_EXTRA_ARGS% /include=%INCLUDE_PATH% /output=%OUTPUT_PATH% %INPUT_PATH% ...and everything works perfectly! HTH, Dave -----Original Message----- From: Brandon Craig Rhodes Sent: 28 May 2010 21:36 To: Dave Hirschfeld Cc: pythondotnet@python.org Subject: Re: [Python.NET] how can I build an assembly I can AddReference()? Brandon Craig Rhodes <brandon@rhodesmill.org> writes:
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. The information transmitted is the property of Gazprom Marketing & Trading Ltd and is intended only for the person or entity to which it is addressed and may contain confidential and/or privileged material. Statements and opinions expressed in this e-mail may not represent those of the company. Any review, retransmission, dissemination and other use of, or taking of any action in reliance upon, this information by persons or entities other than the intended recipient is prohibited. If you received this in error, please contact the sender immediately and delete the material from any computer. Registered office: Gazprom Marketing & Trading Ltd, Gazprom House, 60 Marina Place, Hampton Wick, Kingston upon Thames, KT1 4BH. Registered in England No. 3768267
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@rhodesmill.org http://rhodesmill.org/brandon
It's been pretty quiet on the list lately, so I post a couple of helpful tips: Instead of using the "normal CPython" executable, I find it useful to choose [PathToSolution]/python.exe which is a Managed Code way of loading the pythonxx.dll and allows you to step out of the interpreter main loop when your script exits. Using a cool IDE (like Boa Constructor) which lets you set the interpreter, I also choose [PathToSolution]/python.exe. This makes running [PathToProject]/src/tests/runtests.py (which imports the Pythnon.Test managed test assembly) a snap! This all works thanks to the Post-build event command line of the projects: Python.Runtime: call "$(ProjectDir)buildclrmodule.bat" $(Platform) "$(ProjectDir)" "$(TargetDir)clr.pyd" copy "$(TargetPath)" "$(SolutionDir)" copy "$(TargetDir)*.pdb" "$(SolutionDir)" copy "$(TargetDir)clr.pyd" "$(SolutionDir)" Python.Test: copy "$(TargetPath)" "$(SolutionDir)" copy "$(TargetDir)*.pdb" "$(SolutionDir)" Speaking of runtests.py, it still doesn't run to completion. I'll be working on the Int64 issue shortly. Barton Windows 7 Python 2.6
participants (4)
-
Barton
-
Brandon Craig Rhodes
-
Dave Hirschfeld
-
David Hirschfeld