[IronPython] Need help to port-dynamic class generation code to IP2

เสกสรรค์ sakesun at boonthavorn.com
Sun Apr 20 15:13:20 CEST 2008



	    Unless I simplify my question, I believe there will be a very
little chance
 I will get some help.  So, here is my renewed question. 

	    I'm now using IronPython to implement service components in an
 framework (RemObjects DataAbstract, if that matter)  The framework
require that
 any service component must meet these requirement 

	    1. Extend from their base class.
     2. Its constructor cannot contains any arguments 

	    The framework use Attribute that attached to the base class they
 to discover all available services and then instantiate it via the

	    Since IronPython can extend any .NET base class seamlessly, the
 requirement is not an issue. However, the generated IronPython
 will always equipped with constructor with one argument that link
 static class to its dynamic type. Here come the trouble. 

	    Motivated by my intensive dynamic language preference, I
 with System.Reflection and IronPython source code and came up with
 a solution to subclass any python type to a new class that meet the
 requirement.  The solution is simply use System.Reflection to emit
 the clase like this 
 // C#
 class : 

	    public static  pyType;  // dynamictype is UserType or PythonType

	    public (): base(pyType)        // call base constructor with
pyType as argument

     Of course, the "pyType" static field will have to be set to its
 dynamic type prior to it's usage. (Note that "__init__" won't be
called with 
 this approach.) 

	    This solution work fine for IronPython 1.1 and allow me to keep
my development
 progress until recently that I start exploring IronPython 2.0 (due
to memory 
 leak problem in 1.1) 

	    Porting from 1.0 to 2.0 require changing UserType to PythonType
 After change, the code can emit valid class without error but the
 cause the system to halt. 

	    I'm not sure whether my working approach in 1.1 is just a
obscure trick
 that should never be rely on, or is it just a bug in 2.0.  Hope I
can find
 the answer here. 

	   Thanks in advance 

	   Here is the complete code to demonstrate the problem: 
 ### demo.py ### 

	import clr
 from System.Data import DataTable
 from System import Array, Type, Reflection
 TypeArray = Array[Type] 

	# initialize global constants & variables
 ASSEMBLY_NAME = 'MyDynamicAssembly'
 MODULE_NAME = 'DynamicModule'
 from System import AppDomain
 _domain = AppDomain.CurrentDomain
 _assemblyname = Reflection.AssemblyName()
 _assemblyname.Name = ASSEMBLY_NAME
 _assembly = _domain.DefineDynamicAssembly(_assemblyname,
 _module = _assembly.DefineDynamicModule(MODULE_NAME) 
 # I'm usinge DataTable as an example of the class that need to be
 class PyDataTable(DataTable):
     def show(self):
         print 'Extended !' 

	def define_type(module, name, base):
     attrs = Reflection.TypeAttributes.Public | 
             Reflection.TypeAttributes.Class | 
             Reflection.TypeAttributes.AutoClass | 
             Reflection.TypeAttributes.AnsiClass | 
             Reflection.TypeAttributes.BeforeFieldInit | 
     return module.DefineType(name, attrs, base) 

	def define_field(t, name, typ):
     attrs = Reflection.FieldAttributes.Public | 
     return t.DefineField(name, typ, attrs) 

	def define_constructor(t):
     attrs = Reflection.MethodAttributes.Public | 
     return t.DefineConstructor(attrs,
Reflection.CallingConventions.Standard, TypeArray([])) 

	def common_wrap(BaseClass, name, dynamictype):
     # // use System.Reflection.Emit to make a class
     # // C#
     # class : 
     # {
     #     public static  pyType;  // reference to UserType or
     #     public (): base(pyType)        // call base constructor
with pyType as argument
     #     {
     #     }
     # }
     global _module
     from IronPython.Runtime import Types
     dytype = clr.GetClrType(dynamictype)
     base = clr.GetClrType(BaseClass)
     t = define_type(_module, name, base)
     pyType = define_field(t, 'pyType', dytype)
     base_ctor = base.GetConstructor(TypeArray([dytype]))
     ctor = define_constructor(t)
     g = ctor.GetILGenerator()
     from System.Reflection.Emit.OpCodes import Ldarg_0, Ldsfld,
Call, Ret
     g.Emit(Ldsfld, pyType)
     g.Emit(Call, base_ctor)
     r = clr.GetPythonType(t.CreateType())
     r.pyType = BaseClass
     return r 

	def wrap_1(BaseClass, name):
     from IronPython.Runtime import Types
     return common_wrap(BaseClass, name, Types.UserType) 

	def wrap_2(BaseClass, name):
     from IronPython.Runtime import Types
     return common_wrap(BaseClass, name, Types.PythonType)
 def wrap(BaseClass, name):
     import sys
     if 'IronPython 2.0' in sys.version:
         return wrap_2(BaseClass, name)
         return wrap_1(BaseClass, name)
 WrappedPyDataTable = wrap(PyDataTable, 'WrappedPyDataTable')
 w = WrappedPyDataTable() 

	print 'in 2.0 any action perform to "w" will cause system to halt'
Msg sent via @Mail Softnix Messaging Server http://www.softnix.co.th
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/ironpython-users/attachments/20080420/305866cb/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ask_for_help.py
Type: application/octet-stream
Size: 3218 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/ironpython-users/attachments/20080420/305866cb/attachment.obj>

More information about the Ironpython-users mailing list