From 27fb3c3703018be07543ee1d54948412a3829d2d Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Sat, 1 Aug 2020 12:17:20 -0500 Subject: [PATCH 01/13] Start to implement PyType_FromSpec type approach --- src/runtime/runtime.cs | 3 + src/runtime/typemanager.cs | 305 +++++++++++++++++++++++++++++++++++++ 2 files changed, 308 insertions(+) diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index f63b1feae..189455b4d 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -1726,6 +1726,9 @@ internal static IntPtr PyType_GenericAlloc(IntPtr type, long n) return PyType_GenericAlloc(type, new IntPtr(n)); } + [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr PyType_FromSpec(IntPtr spec); + [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr PyType_GenericAlloc(IntPtr type, IntPtr n); diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 04d40a2ba..644334d2b 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -202,6 +202,17 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) return type; } + static PY_TYPE_SLOT InitializeSlot(int slotNumber, MethodInfo method) + { + var thunk = Interop.GetThunk(method); + return new PY_TYPE_SLOT { slot = slotNumber, func = thunk.Address}; + } + + static PY_TYPE_SLOT InitializeSlot(int slotNumber, IntPtr thunk) + { + return new PY_TYPE_SLOT { slot = slotNumber, func = thunk.Address }; + } + static void InitializeSlot(IntPtr type, int slotOffset, MethodInfo method) { var thunk = Interop.GetThunk(method); @@ -422,6 +433,227 @@ internal static IntPtr BasicSubType(string name, IntPtr base_, Type impl) return type; } + internal class TypeSlots + { + internal static int getSlotNumber(string methodName) + { + Type typeSlotsType = typeof(TypeSlots); + FieldInfo[] fi = typeSlotsType.GetFields(); + var field = typeSlotsType.GetField(methodName); + return (int)field.GetValue(null); + } + + internal static int bf_getbuffer = 1; + internal static int bf_releasebuffer = 2; + internal static int mp_ass_subscript = 3; + internal static int mp_length = 4; + internal static int mp_subscript = 5; + internal static int nb_absolute = 6; + internal static int nb_add = 7; + internal static int nb_and = 8; + internal static int nb_bool = 9; + internal static int nb_divmod = 10; + internal static int nb_float = 11; + internal static int nb_floor_divide = 12; + internal static int nb_index = 13; + internal static int nb_inplace_add = 14; + internal static int nb_inplace_and = 15; + internal static int nb_inplace_floor_divide = 16; + internal static int nb_inplace_lshift = 17; + internal static int nb_inplace_multiply = 18; + internal static int nb_inplace_or = 19; + internal static int nb_inplace_power = 20; + internal static int nb_inplace_remainder = 21; + internal static int nb_inplace_rshift = 22; + internal static int nb_inplace_subtract = 23; + internal static int nb_inplace_true_divide = 24; + internal static int nb_inplace_xor = 25; + internal static int nb_int = 26; + internal static int nb_invert = 27; + internal static int nb_lshift = 28; + internal static int nb_multiply = 29; + internal static int nb_negative = 30; + internal static int nb_or = 31; + internal static int nb_positive = 32; + internal static int nb_power = 33; + internal static int nb_remainder = 34; + internal static int nb_rshift = 35; + internal static int nb_subtract = 36; + internal static int nb_true_divide = 37; + internal static int nb_xor = 38; + internal static int sq_ass_item = 39; + internal static int sq_concat = 40; + internal static int sq_contains = 41; + internal static int sq_inplace_concat = 42; + internal static int sq_inplace_repeat = 43; + internal static int sq_item = 44; + internal static int sq_length = 45; + internal static int sq_repeat = 46; + internal static int tp_alloc = 47; + internal static int tp_base = 48; + internal static int tp_bases = 49; + internal static int tp_call = 50; + internal static int tp_clear = 51; + internal static int tp_dealloc = 52; + internal static int tp_del = 53; + internal static int tp_descr_get = 54; + internal static int tp_descr_set = 55; + internal static int tp_doc = 56; + internal static int tp_getattr = 57; + internal static int tp_getattro = 58; + internal static int tp_hash = 59; + internal static int tp_init = 60; + internal static int tp_is_gc = 61; + internal static int tp_iter = 62; + internal static int tp_iternext = 63; + internal static int tp_methods = 64; + internal static int tp_new = 65; + internal static int tp_repr = 66; + internal static int tp_richcompare = 67; + internal static int tp_setattr = 68; + internal static int tp_setattro = 69; + internal static int tp_str = 70; + internal static int tp_traverse = 71; + internal static int tp_members = 72; + internal static int tp_getset = 73; + internal static int tp_free = 74; + internal static int nb_matrix_multiply = 75; + internal static int nb_inplace_matrix_multiply = 76; + internal static int am_await = 77; + internal static int am_aiter = 78; + internal static int am_anext = 79; + internal static int tp_finalize = 80; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct PY_TYPE_SLOT + { + public long slot; //slot id, from typeslots.h + public IntPtr func; //function pointer of the function implementing the slot + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + internal class PyTypeSpecOffset + { + static PyTypeSpecOffset() + { + Type type = typeof(PyTypeSpecOffset); + FieldInfo[] fi = type.GetFields(); + int size = IntPtr.Size; + for (int i = 0; i < fi.Length; i++) + { + fi[i].SetValue(null, i * size + TypeOffset.ob_size); + } + } + + static IntPtr ToSlotArray(PY_TYPE_SLOT[] type_slots) + { + //type_slots *must* be terminated by a {0,0} entry. Should I check/throw? + + //convert type slot array into intptr + int structSize = Marshal.SizeOf(typeof(PY_TYPE_SLOT)); + GCHandle pinnedArray = GCHandle.Alloc(type_slots, GCHandleType.Pinned); + + IntPtr ptr = pinnedArray.AddrOfPinnedObject(); + return ptr; //Well, this leaks. Lets' come back to this + } + + static void foo(IntPtr doc, IntPtr dealloc, IntPtr call, IntPtr traverse, IntPtr clear, IntPtr members, IntPtr new_) + { + var x = new PY_TYPE_SLOT[] + { + new PY_TYPE_SLOT {slot = TypeSlots.tp_doc, func = doc }, + new PY_TYPE_SLOT {slot = TypeSlots.tp_dealloc, func = dealloc }, + new PY_TYPE_SLOT {slot = TypeSlots.tp_call, func = call }, + new PY_TYPE_SLOT {slot = TypeSlots.tp_traverse, func = traverse }, + new PY_TYPE_SLOT {slot = TypeSlots.tp_clear, func = clear }, + new PY_TYPE_SLOT {slot = TypeSlots.tp_members, func = members }, + new PY_TYPE_SLOT {slot = TypeSlots.tp_new, func = new_ }, + new PY_TYPE_SLOT {slot = 0, func = IntPtr.Zero } + }; + + var arr = ToSlotArray(x); + + } + + public static IntPtr AllocPyTypeSpec(string typename, int obSize, int obFlags, IntPtr slotsPtr) + { + byte[] ascii = System.Text.Encoding.ASCII.GetBytes(typename); + + //This approach is the same as the one in interop.cs for AllocModuleDef + //allocate the size of the struct (which is given by the value of the last + //static member and enough space to hold to typename as a char buffer. The + //amount of space needed is the length of the string and the null terminator + //char* name member will simply point to the position of the buffer. + int size = name_value + ascii.Length + 1; + IntPtr ptr = Marshal.AllocHGlobal(size); + + Marshal.Copy(ascii, 0, ptr + name_value, ascii.Length); + Marshal.WriteIntPtr(ptr, name, ptr + name_value); + Marshal.WriteByte(ptr, name + ascii.Length, 0); + + Util.WriteCLong(ptr, basicsize, obSize); + Util.WriteCLong(ptr, itemsize, 0); + Util.WriteCLong(ptr, flags, obFlags); + + Marshal.WriteIntPtr(ptr, slots, slotsPtr); + return ptr; + } + + public static int name = 0; + public static int basicsize = 0; + public static int itemsize = 0; + public static int flags = 0; + public static int slots = 0; + + private static int name_value = 0; + } + + + internal static IntPtr AllocateTypeObject(string name, PY_TYPE_SLOT[] type_slots) + { + //type_slots *must* be terminated by a {0,0} entry. TODO - Should I check/throw? + + //convert type slot array into intptr + int structSize = Marshal.SizeOf(typeof(PY_TYPE_SLOT)); + GCHandle pinnedArray = GCHandle.Alloc(type_slots, GCHandleType.Pinned); + + //Well, this will leak. Maybe pinnedArray should be added as a member to managedtype. + IntPtr slotsPtr = pinnedArray.AddrOfPinnedObject(); + //pinnedArray.Free(); //at some point + + //create a type from the spec and return it. + IntPtr specPtr = PyTypeSpecOffset.AllocPyTypeSpec(name, 0, 0, slotsPtr); + IntPtr typePtr = Runtime.PyType_FromSpec(specPtr); + return typePtr; + + /* + // Cheat a little: we'll set tp_name to the internal char * of + // the Python version of the type name - otherwise we'd have to + // allocate the tp_name and would have no way to free it. + IntPtr temp = Runtime.PyUnicode_FromString(name); + IntPtr raw = Runtime.PyUnicode_AsUTF8(temp); + Marshal.WriteIntPtr(type, TypeOffset.tp_name, raw); + Marshal.WriteIntPtr(type, TypeOffset.name, temp); + + Marshal.WriteIntPtr(type, TypeOffset.qualname, temp); + + long ptr = type.ToInt64(); // 64-bit safe + + temp = new IntPtr(ptr + TypeOffset.nb_add); + Marshal.WriteIntPtr(type, TypeOffset.tp_as_number, temp); + + temp = new IntPtr(ptr + TypeOffset.sq_length); + Marshal.WriteIntPtr(type, TypeOffset.tp_as_sequence, temp); + + temp = new IntPtr(ptr + TypeOffset.mp_length); + Marshal.WriteIntPtr(type, TypeOffset.tp_as_mapping, temp); + + temp = new IntPtr(ptr + TypeOffset.bf_getbuffer); + Marshal.WriteIntPtr(type, TypeOffset.tp_as_buffer, temp); + return type; + */ + } /// /// Utility method to allocate a type object & do basic initialization. @@ -680,6 +912,79 @@ internal static void InitializeNativeCodePage() } #endregion + /// + /// Given a newly allocated Python type object and a managed Type that + /// provides the implementation for the type, connect the type slots of + /// the Python object to the managed methods of the implementing Type. + /// + internal PY_TYPE_SLOT[] InitializeSlots(Type impl) + { + // We work from the most-derived class up; make sure to get + // the most-derived slot and not to override it with a base + // class's slot. + var seen = new HashSet(); + var typeslots = new List(); + + while (impl != null) + { + MethodInfo[] methods = impl.GetMethods(tbFlags); + foreach (MethodInfo method in methods) + { + string name = method.Name; + if (!(name.StartsWith("tp_") || + name.StartsWith("nb_") || + name.StartsWith("sq_") || + name.StartsWith("mp_") || + name.StartsWith("bf_") + )) + { + continue; + } + + if (seen.Contains(name)) + { + continue; + } + + typeslots.Add(InitializeSlot(TypeSlots.getSlotNumber(name), method)); + seen.Add(name); + } + + impl = impl.BaseType; + } + + var native = NativeCode.Active; + + // The garbage collection related slots always have to return 1 or 0 + // since .NET objects don't take part in Python's gc: + // tp_traverse (returns 0) + // tp_clear (returns 0) + // tp_is_gc (returns 1) + // These have to be defined, though, so by default we fill these with + // static C# functions from this class. + + var ret0 = Interop.GetThunk(((Func)Return0).Method).Address; + var ret1 = Interop.GetThunk(((Func)Return1).Method).Address; + + if (native != null) + { + // If we want to support domain reload, the C# implementation + // cannot be used as the assembly may get released before + // CPython calls these functions. Instead, for amd64 and x86 we + // load them into a separate code page that is leaked + // intentionally. + InitializeNativeCodePage(); + ret1 = NativeCodePage + native.Return1; + ret0 = NativeCodePage + native.Return0; + } + + typeslots.Add(InitializeSlot(TypeSlots.getSlotNumber("tp_traverse"), ret0)); + typeslots.Add(InitializeSlot(TypeSlots.getSlotNumber("tp_clear"), ret0)); + typeslots.Add(InitializeSlot(TypeSlots.getSlotNumber("tp_is_gc"), ret1)); + + return typeslots.ToArray(); + } + /// /// Given a newly allocated Python type object and a managed Type that /// provides the implementation for the type, connect the type slots of From bd26014840660beaa6b8f434577879b7a2e777e0 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Sat, 1 Aug 2020 12:21:10 -0500 Subject: [PATCH 02/13] remove unused code --- src/runtime/typemanager.cs | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 644334d2b..186bfb8b0 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -546,36 +546,6 @@ static PyTypeSpecOffset() } } - static IntPtr ToSlotArray(PY_TYPE_SLOT[] type_slots) - { - //type_slots *must* be terminated by a {0,0} entry. Should I check/throw? - - //convert type slot array into intptr - int structSize = Marshal.SizeOf(typeof(PY_TYPE_SLOT)); - GCHandle pinnedArray = GCHandle.Alloc(type_slots, GCHandleType.Pinned); - - IntPtr ptr = pinnedArray.AddrOfPinnedObject(); - return ptr; //Well, this leaks. Lets' come back to this - } - - static void foo(IntPtr doc, IntPtr dealloc, IntPtr call, IntPtr traverse, IntPtr clear, IntPtr members, IntPtr new_) - { - var x = new PY_TYPE_SLOT[] - { - new PY_TYPE_SLOT {slot = TypeSlots.tp_doc, func = doc }, - new PY_TYPE_SLOT {slot = TypeSlots.tp_dealloc, func = dealloc }, - new PY_TYPE_SLOT {slot = TypeSlots.tp_call, func = call }, - new PY_TYPE_SLOT {slot = TypeSlots.tp_traverse, func = traverse }, - new PY_TYPE_SLOT {slot = TypeSlots.tp_clear, func = clear }, - new PY_TYPE_SLOT {slot = TypeSlots.tp_members, func = members }, - new PY_TYPE_SLOT {slot = TypeSlots.tp_new, func = new_ }, - new PY_TYPE_SLOT {slot = 0, func = IntPtr.Zero } - }; - - var arr = ToSlotArray(x); - - } - public static IntPtr AllocPyTypeSpec(string typename, int obSize, int obFlags, IntPtr slotsPtr) { byte[] ascii = System.Text.Encoding.ASCII.GetBytes(typename); From 81ba32ca7ab3a7d5d5bec1c1a1a044a7cb592468 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Sat, 1 Aug 2020 12:22:50 -0500 Subject: [PATCH 03/13] always add null slot --- src/runtime/typemanager.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 186bfb8b0..d76d1e0d9 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -210,7 +210,7 @@ static PY_TYPE_SLOT InitializeSlot(int slotNumber, MethodInfo method) static PY_TYPE_SLOT InitializeSlot(int slotNumber, IntPtr thunk) { - return new PY_TYPE_SLOT { slot = slotNumber, func = thunk.Address }; + return new PY_TYPE_SLOT { slot = slotNumber, func = thunk }; } static void InitializeSlot(IntPtr type, int slotOffset, MethodInfo method) @@ -952,6 +952,7 @@ internal PY_TYPE_SLOT[] InitializeSlots(Type impl) typeslots.Add(InitializeSlot(TypeSlots.getSlotNumber("tp_clear"), ret0)); typeslots.Add(InitializeSlot(TypeSlots.getSlotNumber("tp_is_gc"), ret1)); + typeslots.Add(new PY_TYPE_SLOT { slot = 0, func = IntPtr.Zero }); return typeslots.ToArray(); } From 44d364e90f7cc65d50d579abb66a69df5e57bfdc Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Sat, 1 Aug 2020 12:27:46 -0500 Subject: [PATCH 04/13] change CreateType --- src/runtime/typemanager.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index d76d1e0d9..8e2112ef7 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -81,7 +81,8 @@ internal static IntPtr GetTypeHandle(ManagedType obj, Type type) /// internal static IntPtr CreateType(Type impl) { - IntPtr type = AllocateTypeObject(impl.Name); + var slotArray = CreateSlotArray(impl); + IntPtr type = AllocateTypeObject(impl.Name, slotArray); int ob_size = ObjectOffset.Size(type); // Set tp_basicsize to the size of our managed instance objects. @@ -90,13 +91,13 @@ internal static IntPtr CreateType(Type impl) var offset = (IntPtr)ObjectOffset.TypeDictOffset(type); Marshal.WriteIntPtr(type, TypeOffset.tp_dictoffset, offset); - InitializeSlots(type, impl); + //InitializeSlots(type, impl); int flags = TypeFlags.Default | TypeFlags.Managed | TypeFlags.HeapType | TypeFlags.HaveGC; Util.WriteCLong(type, TypeOffset.tp_flags, flags); - Runtime.PyType_Ready(type); + //Runtime.PyType_Ready(type); IntPtr dict = Marshal.ReadIntPtr(type, TypeOffset.tp_dict); IntPtr mod = Runtime.PyString_FromString("CLR"); @@ -883,11 +884,10 @@ internal static void InitializeNativeCodePage() #endregion /// - /// Given a newly allocated Python type object and a managed Type that - /// provides the implementation for the type, connect the type slots of - /// the Python object to the managed methods of the implementing Type. + /// Given a managed Type that provides the implementation for the type, + /// create a PY_TYPE_SLOT array to be used for PyType_FromSpec. /// - internal PY_TYPE_SLOT[] InitializeSlots(Type impl) + internal static PY_TYPE_SLOT[] CreateSlotArray(Type impl) { // We work from the most-derived class up; make sure to get // the most-derived slot and not to override it with a base From 1eb7f32eec94c0cd0b6e9e124d38e8c0d3efc2df Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Sat, 1 Aug 2020 12:29:58 -0500 Subject: [PATCH 05/13] add comment --- src/runtime/typemanager.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 8e2112ef7..9efbcf966 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -598,7 +598,8 @@ internal static IntPtr AllocateTypeObject(string name, PY_TYPE_SLOT[] type_slots IntPtr typePtr = Runtime.PyType_FromSpec(specPtr); return typePtr; - /* + //TODO - taken from the other overload. I have no idea what this is meant to do. + /* // Cheat a little: we'll set tp_name to the internal char * of // the Python version of the type name - otherwise we'd have to // allocate the tp_name and would have no way to free it. From 5a2ccffec882a27e67ebeee5f25e0351f5beda24 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Sun, 2 Aug 2020 13:49:11 -0500 Subject: [PATCH 06/13] some progress & slight refactoring --- src/runtime/interop.cs | 5 + src/runtime/typemanager.cs | 211 ++++++++++++++++++------------------- 2 files changed, 109 insertions(+), 107 deletions(-) diff --git a/src/runtime/interop.cs b/src/runtime/interop.cs index 95f3e5b9f..a56fd4a95 100644 --- a/src/runtime/interop.cs +++ b/src/runtime/interop.cs @@ -164,6 +164,11 @@ public static int TypeDictOffset(IntPtr type) return ManagedDataOffsets.DictOffset(type); } + public static int Size() + { + return size; + } + public static int Size(IntPtr pyType) { if (IsException(pyType)) diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 9efbcf966..6bcd18ec4 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -82,23 +82,23 @@ internal static IntPtr GetTypeHandle(ManagedType obj, Type type) internal static IntPtr CreateType(Type impl) { var slotArray = CreateSlotArray(impl); - IntPtr type = AllocateTypeObject(impl.Name, slotArray); - int ob_size = ObjectOffset.Size(type); + int flags = TypeFlags.Default | TypeFlags.Managed | + TypeFlags.HeapType | TypeFlags.HaveGC; - // Set tp_basicsize to the size of our managed instance objects. - Marshal.WriteIntPtr(type, TypeOffset.tp_basicsize, (IntPtr)ob_size); + IntPtr type = CreateTypeObject(impl.Name, ObjectOffset.Size(), flags, slotArray); + + if (ObjectOffset.Size() != ObjectOffset.Size(type)) + { + //should we reset the size and call PyType_Ready again?? + //how do we deal with the fact that size is based on whether + //the type is an exception type. Should CreateSlotArray + //return a tuple with both the slot array and a flag on + //whether the type array describes an exception or not? + } var offset = (IntPtr)ObjectOffset.TypeDictOffset(type); Marshal.WriteIntPtr(type, TypeOffset.tp_dictoffset, offset); - //InitializeSlots(type, impl); - - int flags = TypeFlags.Default | TypeFlags.Managed | - TypeFlags.HeapType | TypeFlags.HaveGC; - Util.WriteCLong(type, TypeOffset.tp_flags, flags); - - //Runtime.PyType_Ready(type); - IntPtr dict = Marshal.ReadIntPtr(type, TypeOffset.tp_dict); IntPtr mod = Runtime.PyString_FromString("CLR"); Runtime.PyDict_SetItemString(dict, "__module__", mod); @@ -434,96 +434,93 @@ internal static IntPtr BasicSubType(string name, IntPtr base_, Type impl) return type; } - internal class TypeSlots + enum TypeSlots { - internal static int getSlotNumber(string methodName) - { - Type typeSlotsType = typeof(TypeSlots); - FieldInfo[] fi = typeSlotsType.GetFields(); - var field = typeSlotsType.GetField(methodName); - return (int)field.GetValue(null); - } + bf_getbuffer = 1, + bf_releasebuffer = 2, + mp_ass_subscript = 3, + mp_length = 4, + mp_subscript = 5, + nb_absolute = 6, + nb_add = 7, + nb_and = 8, + nb_bool = 9, + nb_divmod = 10, + nb_float = 11, + nb_floor_divide = 12, + nb_index = 13, + nb_inplace_add = 14, + nb_inplace_and = 15, + nb_inplace_floor_divide = 16, + nb_inplace_lshift = 17, + nb_inplace_multiply = 18, + nb_inplace_or = 19, + nb_inplace_power = 20, + nb_inplace_remainder = 21, + nb_inplace_rshift = 22, + nb_inplace_subtract = 23, + nb_inplace_true_divide = 24, + nb_inplace_xor = 25, + nb_int = 26, + nb_invert = 27, + nb_lshift = 28, + nb_multiply = 29, + nb_negative = 30, + nb_or = 31, + nb_positive = 32, + nb_power = 33, + nb_remainder = 34, + nb_rshift = 35, + nb_subtract = 36, + nb_true_divide = 37, + nb_xor = 38, + sq_ass_item = 39, + sq_concat = 40, + sq_contains = 41, + sq_inplace_concat = 42, + sq_inplace_repeat = 43, + sq_item = 44, + sq_length = 45, + sq_repeat = 46, + tp_alloc = 47, + tp_base = 48, + tp_bases = 49, + tp_call = 50, + tp_clear = 51, + tp_dealloc = 52, + tp_del = 53, + tp_descr_get = 54, + tp_descr_set = 55, + tp_doc = 56, + tp_getattr = 57, + tp_getattro = 58, + tp_hash = 59, + tp_init = 60, + tp_is_gc = 61, + tp_iter = 62, + tp_iternext = 63, + tp_methods = 64, + tp_new = 65, + tp_repr = 66, + tp_richcompare = 67, + tp_setattr = 68, + tp_setattro = 69, + tp_str = 70, + tp_traverse = 71, + tp_members = 72, + tp_getset = 73, + tp_free = 74, + nb_matrix_multiply = 75, + nb_inplace_matrix_multiply = 76, + am_await = 77, + am_aiter = 78, + am_anext = 79, + tp_finalize = 80, + } - internal static int bf_getbuffer = 1; - internal static int bf_releasebuffer = 2; - internal static int mp_ass_subscript = 3; - internal static int mp_length = 4; - internal static int mp_subscript = 5; - internal static int nb_absolute = 6; - internal static int nb_add = 7; - internal static int nb_and = 8; - internal static int nb_bool = 9; - internal static int nb_divmod = 10; - internal static int nb_float = 11; - internal static int nb_floor_divide = 12; - internal static int nb_index = 13; - internal static int nb_inplace_add = 14; - internal static int nb_inplace_and = 15; - internal static int nb_inplace_floor_divide = 16; - internal static int nb_inplace_lshift = 17; - internal static int nb_inplace_multiply = 18; - internal static int nb_inplace_or = 19; - internal static int nb_inplace_power = 20; - internal static int nb_inplace_remainder = 21; - internal static int nb_inplace_rshift = 22; - internal static int nb_inplace_subtract = 23; - internal static int nb_inplace_true_divide = 24; - internal static int nb_inplace_xor = 25; - internal static int nb_int = 26; - internal static int nb_invert = 27; - internal static int nb_lshift = 28; - internal static int nb_multiply = 29; - internal static int nb_negative = 30; - internal static int nb_or = 31; - internal static int nb_positive = 32; - internal static int nb_power = 33; - internal static int nb_remainder = 34; - internal static int nb_rshift = 35; - internal static int nb_subtract = 36; - internal static int nb_true_divide = 37; - internal static int nb_xor = 38; - internal static int sq_ass_item = 39; - internal static int sq_concat = 40; - internal static int sq_contains = 41; - internal static int sq_inplace_concat = 42; - internal static int sq_inplace_repeat = 43; - internal static int sq_item = 44; - internal static int sq_length = 45; - internal static int sq_repeat = 46; - internal static int tp_alloc = 47; - internal static int tp_base = 48; - internal static int tp_bases = 49; - internal static int tp_call = 50; - internal static int tp_clear = 51; - internal static int tp_dealloc = 52; - internal static int tp_del = 53; - internal static int tp_descr_get = 54; - internal static int tp_descr_set = 55; - internal static int tp_doc = 56; - internal static int tp_getattr = 57; - internal static int tp_getattro = 58; - internal static int tp_hash = 59; - internal static int tp_init = 60; - internal static int tp_is_gc = 61; - internal static int tp_iter = 62; - internal static int tp_iternext = 63; - internal static int tp_methods = 64; - internal static int tp_new = 65; - internal static int tp_repr = 66; - internal static int tp_richcompare = 67; - internal static int tp_setattr = 68; - internal static int tp_setattro = 69; - internal static int tp_str = 70; - internal static int tp_traverse = 71; - internal static int tp_members = 72; - internal static int tp_getset = 73; - internal static int tp_free = 74; - internal static int nb_matrix_multiply = 75; - internal static int nb_inplace_matrix_multiply = 76; - internal static int am_await = 77; - internal static int am_aiter = 78; - internal static int am_anext = 79; - internal static int tp_finalize = 80; + private static int getSlotNumber(string methodName) + { + return (int)Enum.Parse(typeof(TypeSlots), methodName); } [StructLayout(LayoutKind.Sequential)] @@ -581,7 +578,7 @@ public static IntPtr AllocPyTypeSpec(string typename, int obSize, int obFlags, I } - internal static IntPtr AllocateTypeObject(string name, PY_TYPE_SLOT[] type_slots) + internal static IntPtr CreateTypeObject(string name, int obSize, int obFlags, PY_TYPE_SLOT[] type_slots) { //type_slots *must* be terminated by a {0,0} entry. TODO - Should I check/throw? @@ -594,11 +591,11 @@ internal static IntPtr AllocateTypeObject(string name, PY_TYPE_SLOT[] type_slots //pinnedArray.Free(); //at some point //create a type from the spec and return it. - IntPtr specPtr = PyTypeSpecOffset.AllocPyTypeSpec(name, 0, 0, slotsPtr); + IntPtr specPtr = PyTypeSpecOffset.AllocPyTypeSpec(name, obSize, obFlags, slotsPtr); IntPtr typePtr = Runtime.PyType_FromSpec(specPtr); return typePtr; - //TODO - taken from the other overload. I have no idea what this is meant to do. + //TODO - taken from AllocateTypeObject. I have no idea what this is meant to do. /* // Cheat a little: we'll set tp_name to the internal char * of // the Python version of the type name - otherwise we'd have to @@ -917,7 +914,7 @@ internal static PY_TYPE_SLOT[] CreateSlotArray(Type impl) continue; } - typeslots.Add(InitializeSlot(TypeSlots.getSlotNumber(name), method)); + typeslots.Add(InitializeSlot(getSlotNumber(name), method)); seen.Add(name); } @@ -949,9 +946,9 @@ internal static PY_TYPE_SLOT[] CreateSlotArray(Type impl) ret0 = NativeCodePage + native.Return0; } - typeslots.Add(InitializeSlot(TypeSlots.getSlotNumber("tp_traverse"), ret0)); - typeslots.Add(InitializeSlot(TypeSlots.getSlotNumber("tp_clear"), ret0)); - typeslots.Add(InitializeSlot(TypeSlots.getSlotNumber("tp_is_gc"), ret1)); + typeslots.Add(InitializeSlot(getSlotNumber("tp_traverse"), ret0)); + typeslots.Add(InitializeSlot(getSlotNumber("tp_clear"), ret0)); + typeslots.Add(InitializeSlot(getSlotNumber("tp_is_gc"), ret1)); typeslots.Add(new PY_TYPE_SLOT { slot = 0, func = IntPtr.Zero }); return typeslots.ToArray(); From 68b9d22dc9fb7f94c481cd10af5d7b18b164cc8e Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Sun, 2 Aug 2020 21:19:49 -0500 Subject: [PATCH 07/13] implement some PR suggestions --- src/runtime/typemanager.cs | 39 ++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 6bcd18ec4..05fd400e4 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -434,7 +434,7 @@ internal static IntPtr BasicSubType(string name, IntPtr base_, Type impl) return type; } - enum TypeSlots + internal enum TypeSlots : long { bf_getbuffer = 1, bf_releasebuffer = 2, @@ -526,8 +526,8 @@ private static int getSlotNumber(string methodName) [StructLayout(LayoutKind.Sequential)] internal struct PY_TYPE_SLOT { - public long slot; //slot id, from typeslots.h - public IntPtr func; //function pointer of the function implementing the slot + internal TypeSlots slot; //slot id, from typeslots.h + internal IntPtr func; //function pointer of the function implementing the slot } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] @@ -554,27 +554,30 @@ public static IntPtr AllocPyTypeSpec(string typename, int obSize, int obFlags, I //amount of space needed is the length of the string and the null terminator //char* name member will simply point to the position of the buffer. int size = name_value + ascii.Length + 1; - IntPtr ptr = Marshal.AllocHGlobal(size); + IntPtr specPtr = Marshal.AllocHGlobal(size); - Marshal.Copy(ascii, 0, ptr + name_value, ascii.Length); - Marshal.WriteIntPtr(ptr, name, ptr + name_value); - Marshal.WriteByte(ptr, name + ascii.Length, 0); + Marshal.Copy(ascii, 0, specPtr + name_value, ascii.Length); + Marshal.WriteIntPtr(specPtr, name, specPtr + name_value); + Marshal.WriteByte(specPtr, name + ascii.Length, 0); - Util.WriteCLong(ptr, basicsize, obSize); - Util.WriteCLong(ptr, itemsize, 0); - Util.WriteCLong(ptr, flags, obFlags); + Marshal.WriteInt32(specPtr, basicsize, obSize); + Marshal.WriteInt32(specPtr, itemsize, 0); + Marshal.WriteInt32(specPtr, flags, obSize); + //Util.WriteCLong(specPtr, basicsize, obFlags); + //Util.WriteCLong(specPtr, itemsize, 0); + //Util.WriteCLong(specPtr, flags, obFlags); - Marshal.WriteIntPtr(ptr, slots, slotsPtr); - return ptr; + Marshal.WriteIntPtr(specPtr, slots, slotsPtr); + return specPtr; } - public static int name = 0; - public static int basicsize = 0; - public static int itemsize = 0; - public static int flags = 0; - public static int slots = 0; + public static int name = 16; + public static int basicsize = 24; + public static int itemsize = 28; + public static int flags = 32; + public static int slots = 36; - private static int name_value = 0; + public static int name_value = 44; } From 71c20f20d1adb5db6b3b857846efd7665771a46b Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Mon, 3 Aug 2020 21:50:46 -0500 Subject: [PATCH 08/13] fix memory layout --- src/runtime/typemanager.cs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 05fd400e4..a1f350878 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -203,13 +203,13 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) return type; } - static PY_TYPE_SLOT InitializeSlot(int slotNumber, MethodInfo method) + static PY_TYPE_SLOT InitializeSlot(TypeSlots slotNumber, MethodInfo method) { var thunk = Interop.GetThunk(method); return new PY_TYPE_SLOT { slot = slotNumber, func = thunk.Address}; } - static PY_TYPE_SLOT InitializeSlot(int slotNumber, IntPtr thunk) + static PY_TYPE_SLOT InitializeSlot(TypeSlots slotNumber, IntPtr thunk) { return new PY_TYPE_SLOT { slot = slotNumber, func = thunk }; } @@ -434,7 +434,7 @@ internal static IntPtr BasicSubType(string name, IntPtr base_, Type impl) return type; } - internal enum TypeSlots : long + internal enum TypeSlots : int { bf_getbuffer = 1, bf_releasebuffer = 2, @@ -518,9 +518,9 @@ internal enum TypeSlots : long tp_finalize = 80, } - private static int getSlotNumber(string methodName) + private static TypeSlots getSlotNumber(string methodName) { - return (int)Enum.Parse(typeof(TypeSlots), methodName); + return (TypeSlots)Enum.Parse(typeof(TypeSlots), methodName); } [StructLayout(LayoutKind.Sequential)] @@ -558,11 +558,11 @@ public static IntPtr AllocPyTypeSpec(string typename, int obSize, int obFlags, I Marshal.Copy(ascii, 0, specPtr + name_value, ascii.Length); Marshal.WriteIntPtr(specPtr, name, specPtr + name_value); - Marshal.WriteByte(specPtr, name + ascii.Length, 0); + Marshal.WriteByte(specPtr, name_value + ascii.Length, 0); Marshal.WriteInt32(specPtr, basicsize, obSize); Marshal.WriteInt32(specPtr, itemsize, 0); - Marshal.WriteInt32(specPtr, flags, obSize); + Marshal.WriteInt32(specPtr, flags, obFlags); //Util.WriteCLong(specPtr, basicsize, obFlags); //Util.WriteCLong(specPtr, itemsize, 0); //Util.WriteCLong(specPtr, flags, obFlags); @@ -571,13 +571,13 @@ public static IntPtr AllocPyTypeSpec(string typename, int obSize, int obFlags, I return specPtr; } - public static int name = 16; - public static int basicsize = 24; - public static int itemsize = 28; - public static int flags = 32; - public static int slots = 36; + public static int name = 0; + public static int basicsize = name + IntPtr.Size; + public static int itemsize = basicsize + 4; + public static int flags = itemsize + 4; + public static int slots = flags + 4; - public static int name_value = 44; + public static int name_value = slots + IntPtr.Size; } From 5a8da7b73c6758c913545b6f80d7ed7319eb9bef Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Mon, 3 Aug 2020 21:58:19 -0500 Subject: [PATCH 09/13] remove static constructor --- src/runtime/typemanager.cs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index a1f350878..3ff80cc4d 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -533,17 +533,6 @@ internal struct PY_TYPE_SLOT [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] internal class PyTypeSpecOffset { - static PyTypeSpecOffset() - { - Type type = typeof(PyTypeSpecOffset); - FieldInfo[] fi = type.GetFields(); - int size = IntPtr.Size; - for (int i = 0; i < fi.Length; i++) - { - fi[i].SetValue(null, i * size + TypeOffset.ob_size); - } - } - public static IntPtr AllocPyTypeSpec(string typename, int obSize, int obFlags, IntPtr slotsPtr) { byte[] ascii = System.Text.Encoding.ASCII.GetBytes(typename); From 358763805014a9b9991401d3767b2a42346649a4 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Thu, 6 Aug 2020 20:18:33 -0500 Subject: [PATCH 10/13] Use struct --- src/runtime/interop38.cs | 4 +- src/runtime/typemanager.cs | 77 ++++++++++++++------------------------ 2 files changed, 31 insertions(+), 50 deletions(-) diff --git a/src/runtime/interop38.cs b/src/runtime/interop38.cs index 9126bca6a..44cdcec40 100644 --- a/src/runtime/interop38.cs +++ b/src/runtime/interop38.cs @@ -139,9 +139,9 @@ public static int magic() public static int sq_inplace_repeat = 0; public static int bf_getbuffer = 0; public static int bf_releasebuffer = 0; - public static int name = 0; + public static int ht_name = 0; public static int ht_slots = 0; - public static int qualname = 0; + public static int ht_qualname = 0; public static int ht_cached_keys = 0; /* here are optional user slots, followed by the members. */ diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 3ff80cc4d..453df20c4 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -530,61 +530,42 @@ internal struct PY_TYPE_SLOT internal IntPtr func; //function pointer of the function implementing the slot } - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - internal class PyTypeSpecOffset + [StructLayout(LayoutKind.Sequential)] + internal struct PyTypeSpec { - public static IntPtr AllocPyTypeSpec(string typename, int obSize, int obFlags, IntPtr slotsPtr) - { - byte[] ascii = System.Text.Encoding.ASCII.GetBytes(typename); - - //This approach is the same as the one in interop.cs for AllocModuleDef - //allocate the size of the struct (which is given by the value of the last - //static member and enough space to hold to typename as a char buffer. The - //amount of space needed is the length of the string and the null terminator - //char* name member will simply point to the position of the buffer. - int size = name_value + ascii.Length + 1; - IntPtr specPtr = Marshal.AllocHGlobal(size); - - Marshal.Copy(ascii, 0, specPtr + name_value, ascii.Length); - Marshal.WriteIntPtr(specPtr, name, specPtr + name_value); - Marshal.WriteByte(specPtr, name_value + ascii.Length, 0); - - Marshal.WriteInt32(specPtr, basicsize, obSize); - Marshal.WriteInt32(specPtr, itemsize, 0); - Marshal.WriteInt32(specPtr, flags, obFlags); - //Util.WriteCLong(specPtr, basicsize, obFlags); - //Util.WriteCLong(specPtr, itemsize, 0); - //Util.WriteCLong(specPtr, flags, obFlags); - - Marshal.WriteIntPtr(specPtr, slots, slotsPtr); - return specPtr; - } - - public static int name = 0; - public static int basicsize = name + IntPtr.Size; - public static int itemsize = basicsize + 4; - public static int flags = itemsize + 4; - public static int slots = flags + 4; - - public static int name_value = slots + IntPtr.Size; + public IntPtr Name; + public int BasicSize; + public int ItemSize; + public int Flags; + public IntPtr Slots; } - internal static IntPtr CreateTypeObject(string name, int obSize, int obFlags, PY_TYPE_SLOT[] type_slots) { - //type_slots *must* be terminated by a {0,0} entry. TODO - Should I check/throw? - //convert type slot array into intptr int structSize = Marshal.SizeOf(typeof(PY_TYPE_SLOT)); GCHandle pinnedArray = GCHandle.Alloc(type_slots, GCHandleType.Pinned); - - //Well, this will leak. Maybe pinnedArray should be added as a member to managedtype. IntPtr slotsPtr = pinnedArray.AddrOfPinnedObject(); - //pinnedArray.Free(); //at some point //create a type from the spec and return it. - IntPtr specPtr = PyTypeSpecOffset.AllocPyTypeSpec(name, obSize, obFlags, slotsPtr); - IntPtr typePtr = Runtime.PyType_FromSpec(specPtr); + byte[] ascii = System.Text.Encoding.ASCII.GetBytes(name); + GCHandle pinnedName = GCHandle.Alloc(ascii, GCHandleType.Pinned); + IntPtr namePtr = pinnedName.AddrOfPinnedObject(); + + var typeSpec = new PyTypeSpec + { + Name = namePtr, + BasicSize = obSize, + ItemSize = 0, + Flags = obFlags, + Slots = slotsPtr + }; + + var x = TypeOffset.ht_name; + + var typePtr = Runtime.PyType_FromSpec(ref typeSpec).DangerousGetAddress(); + pinnedArray.Free(); + pinnedName.Free(); return typePtr; //TODO - taken from AllocateTypeObject. I have no idea what this is meant to do. @@ -595,9 +576,9 @@ internal static IntPtr CreateTypeObject(string name, int obSize, int obFlags, PY IntPtr temp = Runtime.PyUnicode_FromString(name); IntPtr raw = Runtime.PyUnicode_AsUTF8(temp); Marshal.WriteIntPtr(type, TypeOffset.tp_name, raw); - Marshal.WriteIntPtr(type, TypeOffset.name, temp); + Marshal.WriteIntPtr(type, TypeOffset.ht_name, temp); - Marshal.WriteIntPtr(type, TypeOffset.qualname, temp); + Marshal.WriteIntPtr(type, TypeOffset.ht_qualname, temp); long ptr = type.ToInt64(); // 64-bit safe @@ -629,9 +610,9 @@ internal static IntPtr AllocateTypeObject(string name) IntPtr temp = Runtime.PyUnicode_FromString(name); IntPtr raw = Runtime.PyUnicode_AsUTF8(temp); Marshal.WriteIntPtr(type, TypeOffset.tp_name, raw); - Marshal.WriteIntPtr(type, TypeOffset.name, temp); + Marshal.WriteIntPtr(type, TypeOffset.ht_name, temp); - Marshal.WriteIntPtr(type, TypeOffset.qualname, temp); + Marshal.WriteIntPtr(type, TypeOffset.ht_qualname, temp); long ptr = type.ToInt64(); // 64-bit safe From 79d6a6687d84ec4341c2000193e7c64a0cd9c064 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Thu, 6 Aug 2020 20:45:55 -0500 Subject: [PATCH 11/13] push missed change --- src/runtime/runtime.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 189455b4d..350696ded 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -1727,7 +1727,7 @@ internal static IntPtr PyType_GenericAlloc(IntPtr type, long n) } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyType_FromSpec(IntPtr spec); + internal static extern NewReference PyType_FromSpec(ref TypeManager.PyTypeSpec spec); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr PyType_GenericAlloc(IntPtr type, IntPtr n); From 0e74e0d24270921286ba880ac2b5fd9c2e0624fa Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Thu, 6 Aug 2020 20:50:06 -0500 Subject: [PATCH 12/13] rename interop slots improve comments --- src/runtime/interop34.cs | 4 ++-- src/runtime/interop35.cs | 4 ++-- src/runtime/interop36.cs | 4 ++-- src/runtime/interop37.cs | 4 ++-- src/runtime/typemanager.cs | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/runtime/interop34.cs b/src/runtime/interop34.cs index 6857ff2d0..178e62c92 100644 --- a/src/runtime/interop34.cs +++ b/src/runtime/interop34.cs @@ -131,9 +131,9 @@ public static int magic() public static int sq_inplace_repeat = 0; public static int bf_getbuffer = 0; public static int bf_releasebuffer = 0; - public static int name = 0; + public static int ht_name = 0; public static int ht_slots = 0; - public static int qualname = 0; + public static int ht_qualname = 0; public static int ht_cached_keys = 0; /* here are optional user slots, followed by the members. */ diff --git a/src/runtime/interop35.cs b/src/runtime/interop35.cs index a30bfa4fd..a8397a3bd 100644 --- a/src/runtime/interop35.cs +++ b/src/runtime/interop35.cs @@ -136,9 +136,9 @@ public static int magic() public static int sq_inplace_repeat = 0; public static int bf_getbuffer = 0; public static int bf_releasebuffer = 0; - public static int name = 0; + public static int ht_name = 0; public static int ht_slots = 0; - public static int qualname = 0; + public static int ht_qualname = 0; public static int ht_cached_keys = 0; /* here are optional user slots, followed by the members. */ diff --git a/src/runtime/interop36.cs b/src/runtime/interop36.cs index c46bcc2f5..7ba02e202 100644 --- a/src/runtime/interop36.cs +++ b/src/runtime/interop36.cs @@ -136,9 +136,9 @@ public static int magic() public static int sq_inplace_repeat = 0; public static int bf_getbuffer = 0; public static int bf_releasebuffer = 0; - public static int name = 0; + public static int ht_name = 0; public static int ht_slots = 0; - public static int qualname = 0; + public static int ht_qualname = 0; public static int ht_cached_keys = 0; /* here are optional user slots, followed by the members. */ diff --git a/src/runtime/interop37.cs b/src/runtime/interop37.cs index d5fc76ad3..34f92f56d 100644 --- a/src/runtime/interop37.cs +++ b/src/runtime/interop37.cs @@ -136,9 +136,9 @@ public static int magic() public static int sq_inplace_repeat = 0; public static int bf_getbuffer = 0; public static int bf_releasebuffer = 0; - public static int name = 0; + public static int ht_name = 0; public static int ht_slots = 0; - public static int qualname = 0; + public static int ht_qualname = 0; public static int ht_cached_keys = 0; /* here are optional user slots, followed by the members. */ diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 453df20c4..1724e1428 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -542,12 +542,12 @@ internal struct PyTypeSpec internal static IntPtr CreateTypeObject(string name, int obSize, int obFlags, PY_TYPE_SLOT[] type_slots) { - //convert type slot array into intptr + //convert type slot array to PyType_Slot* int structSize = Marshal.SizeOf(typeof(PY_TYPE_SLOT)); GCHandle pinnedArray = GCHandle.Alloc(type_slots, GCHandleType.Pinned); IntPtr slotsPtr = pinnedArray.AddrOfPinnedObject(); - //create a type from the spec and return it. + //convert name to char* byte[] ascii = System.Text.Encoding.ASCII.GetBytes(name); GCHandle pinnedName = GCHandle.Alloc(ascii, GCHandleType.Pinned); IntPtr namePtr = pinnedName.AddrOfPinnedObject(); From 6333888d9070fc8f16de59af6567b80902ec5d60 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Sat, 8 Aug 2020 12:57:03 -0500 Subject: [PATCH 13/13] re-add commented block --- src/runtime/typemanager.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 1724e1428..167c6d541 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -561,15 +561,10 @@ internal static IntPtr CreateTypeObject(string name, int obSize, int obFlags, PY Slots = slotsPtr }; - var x = TypeOffset.ht_name; - - var typePtr = Runtime.PyType_FromSpec(ref typeSpec).DangerousGetAddress(); + var type = Runtime.PyType_FromSpec(ref typeSpec).DangerousGetAddress(); pinnedArray.Free(); pinnedName.Free(); - return typePtr; - //TODO - taken from AllocateTypeObject. I have no idea what this is meant to do. - /* // Cheat a little: we'll set tp_name to the internal char * of // the Python version of the type name - otherwise we'd have to // allocate the tp_name and would have no way to free it. @@ -593,8 +588,8 @@ internal static IntPtr CreateTypeObject(string name, int obSize, int obFlags, PY temp = new IntPtr(ptr + TypeOffset.bf_getbuffer); Marshal.WriteIntPtr(type, TypeOffset.tp_as_buffer, temp); + return type; - */ } ///