11using System ;
22using System . Collections ;
3- using System . Collections . Specialized ;
3+ using System . Collections . Generic ;
4+ using System . Diagnostics ;
45using System . Runtime . InteropServices ;
56using System . Reflection ;
67using System . Text ;
@@ -67,11 +68,47 @@ public ModulePropertyAttribute()
6768 }
6869 }
6970
71+ internal static class ManagedDataOffsets
72+ {
73+ static ManagedDataOffsets ( )
74+ {
75+ FieldInfo [ ] fi = typeof ( ManagedDataOffsets ) . GetFields ( BindingFlags . Static | BindingFlags . Public ) ;
76+ for ( int i = 0 ; i < fi . Length ; i ++ )
77+ {
78+ fi [ i ] . SetValue ( null , - ( i * IntPtr . Size ) - IntPtr . Size ) ;
79+ }
7080
71- [ StructLayout ( LayoutKind . Sequential , CharSet = CharSet . Ansi ) ]
72- internal class ObjectOffset
81+ size = fi . Length * IntPtr . Size ;
82+ }
83+
84+ public static readonly int ob_data ;
85+ public static readonly int ob_dict ;
86+
87+ private static int BaseOffset ( IntPtr type )
88+ {
89+ Debug . Assert ( type != IntPtr . Zero ) ;
90+ int typeSize = Marshal . ReadInt32 ( type , TypeOffset . tp_basicsize ) ;
91+ Debug . Assert ( typeSize > 0 && typeSize <= ExceptionOffset . Size ( ) ) ;
92+ return typeSize ;
93+ }
94+ public static int DataOffset ( IntPtr type )
95+ {
96+ return BaseOffset ( type ) + ob_data ;
97+ }
98+
99+ public static int DictOffset ( IntPtr type )
100+ {
101+ return BaseOffset ( type ) + ob_dict ;
102+ }
103+
104+ public static int Size { get { return size ; } }
105+
106+ private static readonly int size ;
107+ }
108+
109+ internal static class OriginalObjectOffsets
73110 {
74- static ObjectOffset ( )
111+ static OriginalObjectOffsets ( )
75112 {
76113 int size = IntPtr . Size ;
77114 var n = 0 ; // Py_TRACE_REFS add two pointers to PyObject_HEAD
@@ -82,42 +119,58 @@ static ObjectOffset()
82119#endif
83120 ob_refcnt = ( n + 0 ) * size ;
84121 ob_type = ( n + 1 ) * size ;
85- ob_dict = ( n + 2 ) * size ;
86- ob_data = ( n + 3 ) * size ;
87122 }
88123
89- public static int magic ( IntPtr ob )
124+ public static int Size { get { return size ; } }
125+
126+ private static readonly int size =
127+ #if PYTHON_WITH_PYDEBUG
128+ 4 * IntPtr . Size ;
129+ #else
130+ 2 * IntPtr . Size ;
131+ #endif
132+
133+ #if PYTHON_WITH_PYDEBUG
134+ public static int _ob_next ;
135+ public static int _ob_prev ;
136+ #endif
137+ public static int ob_refcnt ;
138+ public static int ob_type ;
139+ }
140+
141+ [ StructLayout ( LayoutKind . Sequential , CharSet = CharSet . Ansi ) ]
142+ internal class ObjectOffset
143+ {
144+ static ObjectOffset ( )
90145 {
91- if ( ( Runtime . PyObject_TypeCheck ( ob , Exceptions . BaseException ) ||
92- ( Runtime . PyType_Check ( ob ) && Runtime . PyType_IsSubtype ( ob , Exceptions . BaseException ) ) ) )
93- {
94- return ExceptionOffset . ob_data ;
95- }
96- return ob_data ;
146+ #if PYTHON_WITH_PYDEBUG
147+ _ob_next = OriginalObjectOffsets . _ob_next ;
148+ _ob_prev = OriginalObjectOffsets . _ob_prev ;
149+ #endif
150+ ob_refcnt = OriginalObjectOffsets . ob_refcnt ;
151+ ob_type = OriginalObjectOffsets . ob_type ;
152+
153+ size = OriginalObjectOffsets . Size + ManagedDataOffsets . Size ;
97154 }
98155
99- public static int DictOffset ( IntPtr ob )
156+ public static int magic ( IntPtr type )
100157 {
101- if ( ( Runtime . PyObject_TypeCheck ( ob , Exceptions . BaseException ) ||
102- ( Runtime . PyType_Check ( ob ) && Runtime . PyType_IsSubtype ( ob , Exceptions . BaseException ) ) ) )
103- {
104- return ExceptionOffset . ob_dict ;
105- }
106- return ob_dict ;
158+ return ManagedDataOffsets . DataOffset ( type ) ;
107159 }
108160
109- public static int Size ( IntPtr ob )
161+ public static int TypeDictOffset ( IntPtr type )
110162 {
111- if ( ( Runtime . PyObject_TypeCheck ( ob , Exceptions . BaseException ) ||
112- ( Runtime . PyType_Check ( ob ) && Runtime . PyType_IsSubtype ( ob , Exceptions . BaseException ) ) ) )
163+ return ManagedDataOffsets . DictOffset ( type ) ;
164+ }
165+
166+ public static int Size ( IntPtr pyType )
167+ {
168+ if ( IsException ( pyType ) )
113169 {
114170 return ExceptionOffset . Size ( ) ;
115171 }
116- #if PYTHON_WITH_PYDEBUG
117- return 6 * IntPtr . Size ;
118- #else
119- return 4 * IntPtr . Size ;
120- #endif
172+
173+ return size ;
121174 }
122175
123176#if PYTHON_WITH_PYDEBUG
@@ -126,8 +179,15 @@ public static int Size(IntPtr ob)
126179#endif
127180 public static int ob_refcnt ;
128181 public static int ob_type ;
129- private static int ob_dict ;
130- private static int ob_data ;
182+ private static readonly int size ;
183+
184+ private static bool IsException ( IntPtr pyObject )
185+ {
186+ var type = Runtime . PyObject_TYPE ( pyObject ) ;
187+ return Runtime . PyObjectType_TypeCheck ( type , Exceptions . BaseException )
188+ || Runtime . PyObjectType_TypeCheck ( type , Runtime . PyTypeType )
189+ && Runtime . PyType_IsSubtype ( pyObject , Exceptions . BaseException ) ;
190+ }
131191 }
132192
133193 [ StructLayout ( LayoutKind . Sequential , CharSet = CharSet . Ansi ) ]
@@ -136,19 +196,17 @@ internal class ExceptionOffset
136196 static ExceptionOffset ( )
137197 {
138198 Type type = typeof ( ExceptionOffset ) ;
139- FieldInfo [ ] fi = type . GetFields ( ) ;
140- int size = IntPtr . Size ;
199+ FieldInfo [ ] fi = type . GetFields ( BindingFlags . Static | BindingFlags . Public ) ;
141200 for ( int i = 0 ; i < fi . Length ; i ++ )
142201 {
143- fi [ i ] . SetValue ( null , ( i * size ) + ObjectOffset . ob_type + size ) ;
202+ fi [ i ] . SetValue ( null , ( i * IntPtr . Size ) + OriginalObjectOffsets . Size ) ;
144203 }
145- }
146204
147- public static int Size ( )
148- {
149- return ob_data + IntPtr . Size ;
205+ size = fi . Length * IntPtr . Size + OriginalObjectOffsets . Size + ManagedDataOffsets . Size ;
150206 }
151207
208+ public static int Size ( ) { return size ; }
209+
152210 // PyException_HEAD
153211 // (start after PyObject_HEAD)
154212 public static int dict = 0 ;
@@ -162,9 +220,7 @@ public static int Size()
162220 public static int suppress_context = 0 ;
163221#endif
164222
165- // extra c# data
166- public static int ob_dict ;
167- public static int ob_data ;
223+ private static readonly int size ;
168224 }
169225
170226
0 commit comments