();
+
+ Type type = typeof(PyIdentifier);
+ foreach (string name in _builtinNames)
+ {
+ IntPtr op = Runtime.PyUnicode_InternFromString(name);
+ SetIntern(name, op);
+ type.GetField(name).SetValue(null, op);
+ }
+ }
+
+ public static void Shutdown()
+ {
+ foreach (var ptr in _intern2strings.Keys)
+ {
+ Runtime.XDecref(ptr);
+ }
+ _string2interns = null;
+ _intern2strings = null;
+ }
+
+ public static string GetManagedString(IntPtr op)
+ {
+ string s;
+ if (TryGetInterned(op, out s))
+ {
+ return s;
+ }
+ return Runtime.GetManagedString(op);
+ }
+
+ public static bool TryGetInterned(IntPtr op, out string s)
+ {
+ return _intern2strings.TryGetValue(op, out s);
+ }
+
+ private static void SetIntern(string s, IntPtr op)
+ {
+ _string2interns.Add(s, op);
+ _intern2strings.Add(op, s);
+ }
+ }
+}
diff --git a/src/runtime/intern_.cs b/src/runtime/intern_.cs
new file mode 100644
index 000000000..f9b3f43ec
--- /dev/null
+++ b/src/runtime/intern_.cs
@@ -0,0 +1,48 @@
+using System;
+
+namespace Python.Runtime
+{
+ static class PyIdentifier
+ {
+ public static IntPtr __name__;
+ public static IntPtr __dict__;
+ public static IntPtr __doc__;
+ public static IntPtr __class__;
+ public static IntPtr __module__;
+ public static IntPtr __file__;
+ public static IntPtr __slots__;
+ public static IntPtr __self__;
+ public static IntPtr __annotations__;
+ public static IntPtr __init__;
+ public static IntPtr __repr__;
+ public static IntPtr __import__;
+ public static IntPtr __builtins__;
+ public static IntPtr builtins;
+ public static IntPtr __overloads__;
+ public static IntPtr Overloads;
+ }
+
+
+ static partial class InternString
+ {
+ private static readonly string[] _builtinNames = new string[]
+ {
+ "__name__",
+ "__dict__",
+ "__doc__",
+ "__class__",
+ "__module__",
+ "__file__",
+ "__slots__",
+ "__self__",
+ "__annotations__",
+ "__init__",
+ "__repr__",
+ "__import__",
+ "__builtins__",
+ "builtins",
+ "__overloads__",
+ "Overloads",
+ };
+ }
+}
diff --git a/src/runtime/intern_.tt b/src/runtime/intern_.tt
new file mode 100644
index 000000000..c7142ec9f
--- /dev/null
+++ b/src/runtime/intern_.tt
@@ -0,0 +1,58 @@
+<#@ template debug="true" hostSpecific="true" #>
+<#@ output extension=".cs" #>
+<#
+ string[] internNames = new string[]
+ {
+ "__name__",
+ "__dict__",
+ "__doc__",
+ "__class__",
+ "__module__",
+ "__file__",
+ "__slots__",
+ "__self__",
+ "__annotations__",
+
+ "__init__",
+ "__repr__",
+ "__import__",
+ "__builtins__",
+
+ "builtins",
+
+ "__overloads__",
+ "Overloads",
+ };
+#>
+using System;
+
+namespace Python.Runtime
+{
+ static class PyIdentifier
+ {
+<#
+ foreach (var name in internNames)
+ {
+#>
+ public static IntPtr <#= name #>;
+<#
+ }
+#>
+ }
+
+
+ static partial class InternString
+ {
+ private static readonly string[] _builtinNames = new string[]
+ {
+<#
+ foreach (var name in internNames)
+ {
+#>
+ "<#= name #>",
+<#
+ }
+#>
+ };
+ }
+}
diff --git a/src/runtime/metatype.cs b/src/runtime/metatype.cs
index f7afd5d6d..84abe28b9 100644
--- a/src/runtime/metatype.cs
+++ b/src/runtime/metatype.cs
@@ -109,7 +109,7 @@ public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw)
}
}
- IntPtr slots = Runtime.PyDict_GetItemString(dict, "__slots__");
+ IntPtr slots = Runtime.PyDict_GetItem(dict, PyIdentifier.__slots__);
if (slots != IntPtr.Zero)
{
return Exceptions.RaiseTypeError("subclasses of managed classes do not support __slots__");
@@ -197,7 +197,7 @@ public static IntPtr tp_call(IntPtr tp, IntPtr args, IntPtr kw)
return IntPtr.Zero;
}
- var init = Runtime.PyObject_GetAttrString(obj, "__init__");
+ var init = Runtime.PyObject_GetAttr(obj, PyIdentifier.__init__);
Runtime.PyErr_Clear();
if (init != IntPtr.Zero)
diff --git a/src/runtime/methodbinding.cs b/src/runtime/methodbinding.cs
index 011d8217d..7a10fcdef 100644
--- a/src/runtime/methodbinding.cs
+++ b/src/runtime/methodbinding.cs
@@ -84,7 +84,7 @@ public static IntPtr tp_getattro(IntPtr ob, IntPtr key)
return IntPtr.Zero;
}
- string name = Runtime.GetManagedString(key);
+ string name = InternString.GetManagedString(key);
switch (name)
{
case "__doc__":
diff --git a/src/runtime/methodobject.cs b/src/runtime/methodobject.cs
index eb3ce8a18..dc23e3ce5 100644
--- a/src/runtime/methodobject.cs
+++ b/src/runtime/methodobject.cs
@@ -133,8 +133,7 @@ public static IntPtr tp_getattro(IntPtr ob, IntPtr key)
return Exceptions.RaiseTypeError("string expected");
}
- string name = Runtime.GetManagedString(key);
- if (name == "__doc__")
+ if (Runtime.PyUnicode_Compare(key, PyIdentifier.__doc__) == 0)
{
IntPtr doc = self.GetDocString();
Runtime.XIncref(doc);
diff --git a/src/runtime/moduleobject.cs b/src/runtime/moduleobject.cs
index 6313975da..c7085d18a 100644
--- a/src/runtime/moduleobject.cs
+++ b/src/runtime/moduleobject.cs
@@ -48,10 +48,10 @@ public ModuleObject(string name)
IntPtr pyfilename = Runtime.PyString_FromString(filename);
IntPtr pydocstring = Runtime.PyString_FromString(docstring);
IntPtr pycls = TypeManager.GetTypeHandle(GetType());
- Runtime.PyDict_SetItemString(dict, "__name__", pyname);
- Runtime.PyDict_SetItemString(dict, "__file__", pyfilename);
- Runtime.PyDict_SetItemString(dict, "__doc__", pydocstring);
- Runtime.PyDict_SetItemString(dict, "__class__", pycls);
+ Runtime.PyDict_SetItem(dict, PyIdentifier.__name__, pyname);
+ Runtime.PyDict_SetItem(dict, PyIdentifier.__file__, pyfilename);
+ Runtime.PyDict_SetItem(dict, PyIdentifier.__doc__, pydocstring);
+ Runtime.PyDict_SetItem(dict, PyIdentifier.__class__, pycls);
Runtime.XDecref(pyname);
Runtime.XDecref(pyfilename);
Runtime.XDecref(pydocstring);
@@ -282,7 +282,7 @@ public static IntPtr tp_getattro(IntPtr ob, IntPtr key)
return op;
}
- string name = Runtime.GetManagedString(key);
+ string name = InternString.GetManagedString(key);
if (name == "__dict__")
{
Runtime.XIncref(self.dict);
diff --git a/src/runtime/pyscope.cs b/src/runtime/pyscope.cs
index fee78b40a..20c933ad2 100644
--- a/src/runtime/pyscope.cs
+++ b/src/runtime/pyscope.cs
@@ -68,8 +68,8 @@ internal PyScope(IntPtr ptr, PyScopeManager manager)
variables = Runtime.PyModule_GetDict(obj);
PythonException.ThrowIfIsNull(variables);
- int res = Runtime.PyDict_SetItemString(
- variables, "__builtins__",
+ int res = Runtime.PyDict_SetItem(
+ variables, PyIdentifier.__builtins__,
Runtime.PyEval_GetBuiltins()
);
PythonException.ThrowIfIsNotZero(res);
diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs
index 1d688ef9a..df6cf7101 100644
--- a/src/runtime/pythonengine.cs
+++ b/src/runtime/pythonengine.cs
@@ -595,8 +595,8 @@ internal static PyObject RunString(string code, IntPtr? globals, IntPtr? locals,
if (globals == IntPtr.Zero)
{
globals = Runtime.PyDict_New();
- Runtime.PyDict_SetItemString(
- globals.Value, "__builtins__",
+ Runtime.PyDict_SetItem(
+ globals.Value, PyIdentifier.__builtins__,
Runtime.PyEval_GetBuiltins()
);
borrowedGlobals = false;
diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs
index 915e1db00..b9f471339 100644
--- a/src/runtime/runtime.cs
+++ b/src/runtime/runtime.cs
@@ -163,7 +163,7 @@ internal static void Initialize(bool initSigs = false, ShutdownMode mode = Shutd
MainManagedThreadId = Thread.CurrentThread.ManagedThreadId;
IsFinalizing = false;
-
+ InternString.Initialize();
GenericUtil.Reset();
PyScopeManager.Reset();
ClassManager.Reset();
@@ -237,7 +237,7 @@ private static void InitPyMembers()
// a wrapper_descriptor, even though dict.__setitem__ is.
//
// object.__init__ seems safe, though.
- op = PyObject_GetAttrString(PyBaseObjectType, "__init__");
+ op = PyObject_GetAttr(PyBaseObjectType, PyIdentifier.__init__);
SetPyMember(ref PyWrapperDescriptorType, PyObject_Type(op),
() => PyWrapperDescriptorType = IntPtr.Zero);
XDecref(op);
@@ -378,6 +378,7 @@ internal static void Shutdown(ShutdownMode mode)
Exceptions.Shutdown();
Finalizer.Shutdown();
+ InternString.Shutdown();
if (mode != ShutdownMode.Normal)
{
@@ -1598,6 +1599,12 @@ internal static IntPtr PyUnicode_FromString(string s)
return PyUnicode_FromUnicode(s, s.Length);
}
+ [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern IntPtr PyUnicode_InternFromString(string s);
+
+ [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int PyUnicode_Compare(IntPtr left, IntPtr right);
+
internal static string GetManagedString(in BorrowedReference borrowedReference)
=> GetManagedString(borrowedReference.DangerousGetAddress());
///
@@ -2183,7 +2190,7 @@ internal static void SetNoSiteFlag()
///
internal static IntPtr GetBuiltins()
{
- return PyImport_ImportModule("builtins");
+ return PyImport_Import(PyIdentifier.builtins);
}
}
diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs
index 78c34a027..43c160bc3 100644
--- a/src/runtime/typemanager.cs
+++ b/src/runtime/typemanager.cs
@@ -165,7 +165,7 @@ internal static IntPtr CreateType(Type impl)
IntPtr dict = Marshal.ReadIntPtr(type, TypeOffset.tp_dict);
IntPtr mod = Runtime.PyString_FromString("CLR");
- Runtime.PyDict_SetItemString(dict, "__module__", mod);
+ Runtime.PyDict_SetItem(dict, PyIdentifier.__module__, mod);
Runtime.XDecref(mod);
InitMethods(type, impl);
@@ -284,7 +284,7 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType)
IntPtr dict = Marshal.ReadIntPtr(type, TypeOffset.tp_dict);
string mn = clrType.Namespace ?? "";
IntPtr mod = Runtime.PyString_FromString(mn);
- Runtime.PyDict_SetItemString(dict, "__module__", mod);
+ Runtime.PyDict_SetItem(dict, PyIdentifier.__module__, mod);
Runtime.XDecref(mod);
// Hide the gchandle of the implementation in a magic type slot.
@@ -564,7 +564,7 @@ internal static IntPtr BasicSubType(string name, IntPtr base_, Type impl)
IntPtr tp_dict = Marshal.ReadIntPtr(type, TypeOffset.tp_dict);
IntPtr mod = Runtime.PyString_FromString("CLR");
- Runtime.PyDict_SetItemString(tp_dict, "__module__", mod);
+ Runtime.PyDict_SetItem(tp_dict, PyIdentifier.__module__, mod);
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