[Users] [IronPython] IronPython Attribute Workaround

Michael Foord fuzzyman at voidspace.org.uk
Tue Jul 24 01:09:38 CEST 2007


I'm pretty sure that it is impossible to dynamically generate classes 
decorated with attributes at runtime using 'pure C#'.

The two alternatives are either to use the Reflection.Emit API - which 
is probably the best way but requires more digging than I have time for 
at this point in time.

Another alternative is to dynamically generate C# and compile to in 
memory assemblies. This is less memory efficient because it requires an 
assembly and type object for every command you wish to add. It is a lot 
faster than you might expect.

Attached are two files. One is 'generate.py'. It has a function called 
'Generate' which compiles C# using the CodeDom API with the 
CSharpCodeProvider.

As an example I have provided another file - DllImport.py. This uses 
Generate to compile the C# from my screenshot example :

http://www.voidspace.org.uk/ironpython/winforms/part10.shtml

It works fine. :-)

The specific call is :

assembly = Generate(unmanaged_code, 'UnamangedCode', inMemory=True)
clr.AddReference(assembly)
from UnmanagedCode import User32, GDI32

(You can also use it to save assemblies to disk.)

For your use you will need to pass in a list of references (absolute 
file paths) to the AutoCAD DLLs that your C# code is dependent on.

I think you need to generate C# code that looks something like:


using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;

namespace AutoCADStuff

{
  public class AutoCADStuffBase
  {
    [CommandMethod("myname")]
    public void method
    {
       _method();
    }

    public virtual void _method
    {
       return null;
    }
}

In IronPython you can call 'Generate', then import and subclass 
AutoCADStuffBase and override '_method':

class AutoCADStuff(AutoCADStuffBase):
    def _method(self):
       some code ...

I have used this approach with Silverlight assemblies for creating 
classes with methods marked with attributes.

I hope this helps.

Please no one post this code as is - I'll write up and post an article 
shortly. :-)

Michael Foord

Michael Foord wrote:
> Tim Riley wrote:
> [snip..]
>   
>>  AutoCAD's .NET API allows
>> you to register a command that is callable from the AutoCAD via a CommandMethod attribute[1]. Since IP doesn't support attributes I'd like to develop some sort of decorator that would clone the functionality of the CommandMethod attribute. So I could execute
>> python code like:
>>
>> @commandmethod("test")
>> def tester:
>>     print "test worked"
>>
>> and it would register the test command so  I could call it from the
>> command line.
>>
>>   
>>     
>
> Right - so you want to dynamically create  methods (or functions) with 
> attributes. The attribute takes the name that the command will be 
> exposed with.
>
> I wonder if AutoCAD even supports these being dynamically created?
>
> If it does I wonder if we can do it by creating an inner class in C#. 
> The method marked with the attribute would call down to another method 
> (marked as virtual) that we can override from IronPython.
>
> I'm not exactly sure of the C# syntax/semantics for inner classes - (a 
> class factory) - so I'll have to do some digging. (i.e. will it allow us 
> to set the argument to the attribute at runtime rather than compile time 
> and can we return classes or only instances.)
>
> AFAIK, attributes are normally bound at compile time rather than 
> runtime, so using C# to create classes in this way may not work.
>
> The proper way (*sigh*) is to use the Reflection.Emit API to add 
> attributes. I've experimented Reflection.Emit - but never got as far as 
> adding attributes dynamically. (You need to 'program in bytecode' using 
> this API - which isn't too bad but has a bit of a learning curve 
> associated.)
>
> A *third* approach is to dynamically generate C# and compile to in 
> memory assemblies (using the CodeDOM API if I remember correctly). That 
> turns out to be surprisingly easy.
>
> Michael Foord
> http://www.voidspace.org.uk/ironpython/index.shtml
>
>   
>> [1] As an example:
>> http://through-the-interface.typepad.com/through_the_interface/2007/07/updating-a-spec.html
>>
>>
>> Tim
>>
>> On 7/23/07, Michael Foord <fuzzyman at voidspace.org.uk> wrote:
>>   
>>     
>>> Tim Riley wrote:
>>>     
>>>       
>>>> Michael:
>>>>
>>>> Thanks for the reply. However when reading it my eyes glazed over. Is
>>>> there any way you could provide a simple man like myself with some
>>>> example code for me to peruse?
>>>>
>>>>       
>>>>         
>>> What do you want to achieve? Write the IronPython code you would like -
>>> and I will try and provide a C# stub that you can subclass. (You will
>>> need a C# compiler - Visual Studio Express C# is probably the most
>>> straightforward if you are using Windows.)
>>>
>>> Michael Foord
>>> http://www.voidspace.org.uk/ironpython/index.shtml
>>>
>>>     
>>>       
>>>> Tim
>>>>
>>>> On 7/23/07, Michael Foord <fuzzyman at voidspace.org.uk> wrote:
>>>>
>>>>       
>>>>         
>>>>> Tim Riley wrote:
>>>>>
>>>>>         
>>>>>           
>>>>>> I know that IronPython doesn't support attributes but does anyone know
>>>>>> of a workaround that will allow IP code to use them?
>>>>>>
>>>>>>
>>>>>>           
>>>>>>             
>>>>> The IronPython team are strangely quiet every time someone asks this... ;-)
>>>>>
>>>>> A lot of people would like an answer to this question. Currently the
>>>>> only way is to use stub C# classes.
>>>>>
>>>>> Michael Foord
>>>>> http://www.voidspace.org.uk/ironpython/index.shtml
>>>>>
>>>>>
>>>>>
>>>>>         
>>>>>           
>>>>>> _______________________________________________
>>>>>> users mailing list
>>>>>> users at lists.ironpython.com
>>>>>> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
>>>>>>
>>>>>>
>>>>>>
>>>>>>           
>>>>>>             
>>>>> _______________________________________________
>>>>> users mailing list
>>>>> users at lists.ironpython.com
>>>>> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
>>>>>
>>>>>
>>>>>         
>>>>>           
>>>> _______________________________________________
>>>> Users mailing list
>>>> Users at lists.ironpython.com
>>>> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
>>>>
>>>>
>>>>       
>>>>         
>>> _______________________________________________
>>> Users mailing list
>>> Users at lists.ironpython.com
>>> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
>>>
>>>     
>>>       
>> _______________________________________________
>> Users mailing list
>> Users at lists.ironpython.com
>> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
>>
>>   
>>     
>
> _______________________________________________
> Users mailing list
> Users at lists.ironpython.com
> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
>
>   

-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: DllImport.py
URL: <http://mail.python.org/pipermail/ironpython-users/attachments/20070724/527d22ed/attachment.ksh>
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: generate.py
URL: <http://mail.python.org/pipermail/ironpython-users/attachments/20070724/527d22ed/attachment-0001.ksh>


More information about the Ironpython-users mailing list