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; - */ } /// pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy