Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
refactoring in CreateSubType
  • Loading branch information
lostmsu committed Dec 18, 2020
commit 08ea6f3c56086f661ba3b0d24daa481509c0be1f
4 changes: 3 additions & 1 deletion src/runtime/converter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,9 @@ internal static bool ToManaged(IntPtr value, Type type,
return Converter.ToManagedValue(value, type, out result, setError);
}


internal static bool ToManagedValue(BorrowedReference value, Type obType,
out object result, bool setError)
=> ToManagedValue(value.DangerousGetAddress(), obType, out result, setError);
internal static bool ToManagedValue(IntPtr value, Type obType,
out object result, bool setError)
{
Expand Down
2 changes: 2 additions & 0 deletions src/runtime/runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1641,6 +1641,8 @@ internal static bool PyDict_Check(IntPtr ob)
/// </summary>
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr PyDict_GetItem(IntPtr pointer, IntPtr key);
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
internal static extern BorrowedReference PyDict_GetItemWithError(BorrowedReference pointer, BorrowedReference key);

/// <summary>
/// Return value: Borrowed reference.
Expand Down
51 changes: 21 additions & 30 deletions src/runtime/typemanager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Runtime.InteropServices;
using System.Diagnostics;
using Python.Runtime.Slots;
using static Python.Runtime.PythonException;

namespace Python.Runtime
{
Expand Down Expand Up @@ -302,6 +303,7 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType)

internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr py_dict)
{
var dictRef = new BorrowedReference(py_dict);
// Utility to create a subtype of a managed type with the ability for the
// a python subtype able to override the managed implementation
string name = Runtime.GetManagedString(py_name);
Expand All @@ -311,40 +313,29 @@ internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr
object assembly = null;
object namespaceStr = null;

var disposeList = new List<PyObject>();
try
using (var assemblyKey = new PyString("__assembly__"))
{
var assemblyKey = new PyObject(Converter.ToPython("__assembly__", typeof(string)));
disposeList.Add(assemblyKey);
if (0 != Runtime.PyMapping_HasKey(py_dict, assemblyKey.Handle))
var assemblyPtr = Runtime.PyDict_GetItemWithError(dictRef, assemblyKey.Reference);
if (assemblyPtr.IsNull)
{
var pyAssembly = new PyObject(Runtime.PyDict_GetItem(py_dict, assemblyKey.Handle));
Runtime.XIncref(pyAssembly.Handle);
disposeList.Add(pyAssembly);
if (!Converter.ToManagedValue(pyAssembly.Handle, typeof(string), out assembly, false))
{
throw new InvalidCastException("Couldn't convert __assembly__ value to string");
}
if (Exceptions.ErrorOccurred()) return IntPtr.Zero;
}
else if (!Converter.ToManagedValue(assemblyPtr, typeof(string), out assembly, false))
{
return Exceptions.RaiseTypeError("Couldn't convert __assembly__ value to string");
}

var namespaceKey = new PyObject(Converter.ToPythonImplicit("__namespace__"));
disposeList.Add(namespaceKey);
if (0 != Runtime.PyMapping_HasKey(py_dict, namespaceKey.Handle))
using (var namespaceKey = new PyString("__namespace__"))
{
var pyNamespace = new PyObject(Runtime.PyDict_GetItem(py_dict, namespaceKey.Handle));
Runtime.XIncref(pyNamespace.Handle);
disposeList.Add(pyNamespace);
if (!Converter.ToManagedValue(pyNamespace.Handle, typeof(string), out namespaceStr, false))
var pyNamespace = Runtime.PyDict_GetItemWithError(dictRef, namespaceKey.Reference);
if (pyNamespace.IsNull)
{
throw new InvalidCastException("Couldn't convert __namespace__ value to string");
if (Exceptions.ErrorOccurred()) return IntPtr.Zero;
}
else if (!Converter.ToManagedValue(pyNamespace, typeof(string), out namespaceStr, false))
{
return Exceptions.RaiseTypeError("Couldn't convert __namespace__ value to string");
}
}
}
finally
{
foreach (PyObject o in disposeList)
{
o.Dispose();
}
}

Expand All @@ -370,14 +361,14 @@ internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr
// by default the class dict will have all the C# methods in it, but as this is a
// derived class we want the python overrides in there instead if they exist.
IntPtr cls_dict = Marshal.ReadIntPtr(py_type, TypeOffset.tp_dict);
Runtime.PyDict_Update(cls_dict, py_dict);
ThrowIfIsNotZero(Runtime.PyDict_Update(cls_dict, py_dict));
Runtime.XIncref(py_type);
// Update the __classcell__ if it exists
var cell = new BorrowedReference(Runtime.PyDict_GetItemString(cls_dict, "__classcell__"));
if (!cell.IsNull)
{
Runtime.PyCell_Set(cell, py_type);
Runtime.PyDict_DelItemString(cls_dict, "__classcell__");
ThrowIfIsNotZero(Runtime.PyCell_Set(cell, py_type));
ThrowIfIsNotZero(Runtime.PyDict_DelItemString(cls_dict, "__classcell__"));
}

return py_type;
Expand Down