diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat
index 811b1bd84d2417..34fa3b97c584ea 100644
--- a/Doc/data/stable_abi.dat
+++ b/Doc/data/stable_abi.dat
@@ -859,6 +859,7 @@ function,Py_NewInterpreter,3.2,,
function,Py_NewRef,3.10,,
function,Py_ReprEnter,3.2,,
function,Py_ReprLeave,3.2,,
+function,Py_SET_REFCNT,3.13,,
function,Py_SetRecursionLimit,3.2,,
type,Py_UCS4,3.2,,
macro,Py_UNBLOCK_THREADS,3.2,,
diff --git a/Include/object.h b/Include/object.h
index 85abd30b5ad7d6..cb16e3736239df 100644
--- a/Include/object.h
+++ b/Include/object.h
@@ -352,15 +352,17 @@ static inline int Py_IS_TYPE(PyObject *ob, PyTypeObject *type) {
#endif
-// Py_SET_REFCNT() implementation for stable ABI
-PyAPI_FUNC(void) _Py_SetRefcnt(PyObject *ob, Py_ssize_t refcnt);
-
-static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) {
#if defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030d0000
- // Stable ABI implements Py_SET_REFCNT() as a function call
- // on limited C API version 3.13 and newer.
- _Py_SetRefcnt(ob, refcnt);
+// Stable ABI implements Py_SET_REFCNT() as a function call
+// on limited C API version 3.13 and newer.
+PyAPI_FUNC(void) Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt);
#else
+
+#ifdef _Py_STABLE_ABI_IMPL
+# define Py_SET_REFCNT _Py_SET_REFCNT
+#endif
+
+static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) {
// This immortal check is for code that is unaware of immortal objects.
// The runtime tracks these objects and we should avoid as much
// as possible having extensions inadvertently change the refcnt
@@ -394,11 +396,11 @@ static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) {
ob->ob_ref_shared = _Py_REF_SHARED(refcnt, _Py_REF_MERGED);
}
#endif // Py_GIL_DISABLED
-#endif // Py_LIMITED_API+0 < 0x030d0000
}
-#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
+#if (!defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000) && !defined(_Py_STABLE_ABI_IMPL)
# define Py_SET_REFCNT(ob, refcnt) Py_SET_REFCNT(_PyObject_CAST(ob), (refcnt))
#endif
+#endif
static inline void Py_SET_TYPE(PyObject *ob, PyTypeObject *type) {
diff --git a/Lib/test/test_stable_abi_ctypes.py b/Lib/test/test_stable_abi_ctypes.py
index 4976ac3642bbe4..1236e345d2bc0d 100644
--- a/Lib/test/test_stable_abi_ctypes.py
+++ b/Lib/test/test_stable_abi_ctypes.py
@@ -870,6 +870,7 @@ def test_windows_feature_macros(self):
"Py_NewRef",
"Py_ReprEnter",
"Py_ReprLeave",
+ "Py_SET_REFCNT",
"Py_SetPath",
"Py_SetProgramName",
"Py_SetPythonHome",
@@ -906,7 +907,6 @@ def test_windows_feature_macros(self):
"_Py_IncRef",
"_Py_NoneStruct",
"_Py_NotImplementedStruct",
- "_Py_SetRefcnt",
"_Py_SwappedOp",
"_Py_TrueStruct",
"_Py_VaBuildValue_SizeT",
diff --git a/Makefile.pre.in b/Makefile.pre.in
index b5edb4e6748fb0..3a58539507c1ce 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -508,6 +508,7 @@ OBJECT_OBJS= \
Objects/moduleobject.o \
Objects/namespaceobject.o \
Objects/object.o \
+ Objects/object_abi.o \
Objects/obmalloc.o \
Objects/picklebufobject.o \
Objects/rangeobject.o \
diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml
index 22b25dd0ec141f..ba589f6e28ab48 100644
--- a/Misc/stable_abi.toml
+++ b/Misc/stable_abi.toml
@@ -2478,6 +2478,5 @@
added = '3.13'
[function.PySys_AuditTuple]
added = '3.13'
-[function._Py_SetRefcnt]
+[function.Py_SET_REFCNT]
added = '3.13'
- abi_only = true
diff --git a/Objects/object.c b/Objects/object.c
index d145674cb3ba34..b9e97dcbdeba31 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -2886,55 +2886,3 @@ PyObject_GET_WEAKREFS_LISTPTR(PyObject *op)
{
return _PyObject_GET_WEAKREFS_LISTPTR(op);
}
-
-
-#undef Py_NewRef
-#undef Py_XNewRef
-
-// Export Py_NewRef() and Py_XNewRef() as regular functions for the stable ABI.
-PyObject*
-Py_NewRef(PyObject *obj)
-{
- return _Py_NewRef(obj);
-}
-
-PyObject*
-Py_XNewRef(PyObject *obj)
-{
- return _Py_XNewRef(obj);
-}
-
-#undef Py_Is
-#undef Py_IsNone
-#undef Py_IsTrue
-#undef Py_IsFalse
-
-// Export Py_Is(), Py_IsNone(), Py_IsTrue(), Py_IsFalse() as regular functions
-// for the stable ABI.
-int Py_Is(PyObject *x, PyObject *y)
-{
- return (x == y);
-}
-
-int Py_IsNone(PyObject *x)
-{
- return Py_Is(x, Py_None);
-}
-
-int Py_IsTrue(PyObject *x)
-{
- return Py_Is(x, Py_True);
-}
-
-int Py_IsFalse(PyObject *x)
-{
- return Py_Is(x, Py_False);
-}
-
-
-// Py_SET_REFCNT() implementation for stable ABI
-void
-_Py_SetRefcnt(PyObject *ob, Py_ssize_t refcnt)
-{
- Py_SET_REFCNT(ob, refcnt);
-}
diff --git a/Objects/object_abi.c b/Objects/object_abi.c
new file mode 100644
index 00000000000000..8e33493e622e02
--- /dev/null
+++ b/Objects/object_abi.c
@@ -0,0 +1,61 @@
+// Stable ABI implementation for PyObject functions.
+
+
+// Rename static inline functions with macros
+#define _Py_STABLE_ABI_IMPL
+
+#include "Python.h"
+
+
+#undef Py_NewRef
+#undef Py_XNewRef
+
+// Export Py_NewRef() and Py_XNewRef() as regular functions for the stable ABI.
+PyObject*
+Py_NewRef(PyObject *obj)
+{
+ return _Py_NewRef(obj);
+}
+
+PyObject*
+Py_XNewRef(PyObject *obj)
+{
+ return _Py_XNewRef(obj);
+}
+
+
+#undef Py_Is
+#undef Py_IsNone
+#undef Py_IsTrue
+#undef Py_IsFalse
+
+// Export Py_Is(), Py_IsNone(), Py_IsTrue(), Py_IsFalse() as regular functions
+// for the stable ABI.
+int Py_Is(PyObject *x, PyObject *y)
+{
+ return (x == y);
+}
+
+int Py_IsNone(PyObject *x)
+{
+ return Py_Is(x, Py_None);
+}
+
+int Py_IsTrue(PyObject *x)
+{
+ return Py_Is(x, Py_True);
+}
+
+int Py_IsFalse(PyObject *x)
+{
+ return Py_Is(x, Py_False);
+}
+
+
+#undef Py_SET_REFCNT
+
+PyAPI_FUNC(void)
+Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt)
+{
+ _Py_SET_REFCNT(ob, refcnt);
+}
diff --git a/PC/python3dll.c b/PC/python3dll.c
index 07aa84c91f9fc7..1e44b1cd0b75e1 100755
--- a/PC/python3dll.c
+++ b/PC/python3dll.c
@@ -19,7 +19,6 @@ EXPORT_FUNC(_Py_Dealloc)
EXPORT_FUNC(_Py_DecRef)
EXPORT_FUNC(_Py_IncRef)
EXPORT_FUNC(_Py_NegativeRefcount)
-EXPORT_FUNC(_Py_SetRefcnt)
EXPORT_FUNC(_Py_VaBuildValue_SizeT)
EXPORT_FUNC(_PyArg_Parse_SizeT)
EXPORT_FUNC(_PyArg_ParseTuple_SizeT)
@@ -81,6 +80,7 @@ EXPORT_FUNC(Py_NewInterpreter)
EXPORT_FUNC(Py_NewRef)
EXPORT_FUNC(Py_ReprEnter)
EXPORT_FUNC(Py_ReprLeave)
+EXPORT_FUNC(Py_SET_REFCNT)
EXPORT_FUNC(Py_SetPath)
EXPORT_FUNC(Py_SetProgramName)
EXPORT_FUNC(Py_SetPythonHome)
diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj
index be1b98dba02fc5..13536fb4e07fec 100644
--- a/PCbuild/pythoncore.vcxproj
+++ b/PCbuild/pythoncore.vcxproj
@@ -503,6 +503,7 @@
+
diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters
index 4f0da8f35998b7..b7d0b7b4536e7a 100644
--- a/PCbuild/pythoncore.vcxproj.filters
+++ b/PCbuild/pythoncore.vcxproj.filters
@@ -1142,6 +1142,9 @@
Objects
+
+ Objects
+
Objects