@@ -88,7 +88,48 @@ public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw) {
8888 ) ;
8989 }
9090
91- return TypeManager . CreateSubType ( name , base_type , dict ) ;
91+ // If __assembly__ or __namespace__ are in the class dictionary then create
92+ // a managed sub type.
93+ // This creates a new managed type that can be used from .net to call back
94+ // into python.
95+ if ( IntPtr . Zero != dict ) {
96+ Runtime . Incref ( dict ) ;
97+ PyDict clsDict = new PyDict ( dict ) ;
98+ if ( clsDict . HasKey ( "__assembly__" ) || clsDict . HasKey ( "__namespace__" ) )
99+ return TypeManager . CreateSubType ( name , base_type , dict ) ;
100+ }
101+
102+ // otherwise just create a basic type without reflecting back into the managed side.
103+ IntPtr func = Marshal . ReadIntPtr ( Runtime . PyTypeType ,
104+ TypeOffset . tp_new ) ;
105+ IntPtr type = NativeCall . Call_3 ( func , tp , args , kw ) ;
106+ if ( type == IntPtr . Zero ) {
107+ return IntPtr . Zero ;
108+ }
109+
110+ int flags = TypeFlags . Default ;
111+ flags |= TypeFlags . Managed ;
112+ flags |= TypeFlags . HeapType ;
113+ flags |= TypeFlags . BaseType ;
114+ flags |= TypeFlags . Subclass ;
115+ flags |= TypeFlags . HaveGC ;
116+ Marshal . WriteIntPtr ( type , TypeOffset . tp_flags , ( IntPtr ) flags ) ;
117+
118+ TypeManager . CopySlot ( base_type , type , TypeOffset . tp_dealloc ) ;
119+
120+ // Hmm - the standard subtype_traverse, clear look at ob_size to
121+ // do things, so to allow gc to work correctly we need to move
122+ // our hidden handle out of ob_size. Then, in theory we can
123+ // comment this out and still not crash.
124+ TypeManager . CopySlot ( base_type , type , TypeOffset . tp_traverse ) ;
125+ TypeManager . CopySlot ( base_type , type , TypeOffset . tp_clear ) ;
126+
127+
128+ // for now, move up hidden handle...
129+ IntPtr gc = Marshal . ReadIntPtr ( base_type , TypeOffset . magic ( ) ) ;
130+ Marshal . WriteIntPtr ( type , TypeOffset . magic ( ) , gc ) ;
131+
132+ return type ;
92133 }
93134
94135
0 commit comments