Skip to content

Commit 5dbd27b

Browse files
committed
gh-115754: Export Py_None, Py_False, Py_True as symbols
In the limited C API and the stable ABI, implement Py_None, Py_False and Py_True constants are symbols.
1 parent 10fc467 commit 5dbd27b

File tree

7 files changed

+52
-1
lines changed

7 files changed

+52
-1
lines changed

Include/boolobject.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,15 @@ extern "C" {
1717
PyAPI_DATA(PyLongObject) _Py_FalseStruct;
1818
PyAPI_DATA(PyLongObject) _Py_TrueStruct;
1919

20-
/* Use these macros */
20+
// Export symbols in the stable ABI
21+
PyAPI_DATA(PyLongObject*) Py_False;
22+
PyAPI_DATA(PyLongObject*) Py_True;
23+
24+
#ifndef Py_LIMITED_API
25+
// Implement Py_False and Py_True as macros in the non-limited C API
2126
#define Py_False _PyObject_CAST(&_Py_FalseStruct)
2227
#define Py_True _PyObject_CAST(&_Py_TrueStruct)
28+
#endif
2329

2430
// Test if an object is the True singleton, the same as "x is True" in Python.
2531
PyAPI_FUNC(int) Py_IsTrue(PyObject *x);

Include/object.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,7 +1070,14 @@ _Py_NoneStruct is an object of undefined type which can be used in contexts
10701070
where NULL (nil) is not suitable (since NULL often means 'error').
10711071
*/
10721072
PyAPI_DATA(PyObject) _Py_NoneStruct; /* Don't use this directly */
1073+
1074+
// Export the symbol in the stable ABI
1075+
PyAPI_DATA(PyObject*) Py_None;
1076+
1077+
#ifndef Py_LIMITED_API
1078+
// Implement Py_None as a macro in the non-limited C API
10731079
#define Py_None (&_Py_NoneStruct)
1080+
#endif
10741081

10751082
// Test if an object is the None singleton, the same as "x is None" in Python.
10761083
PyAPI_FUNC(int) Py_IsNone(PyObject *x);

Lib/test/test_stable_abi_ctypes.py

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
In the limited C API and the stable ABI, implement ``Py_None``, ``Py_False``
2+
and ``Py_True`` constants are symbols, rather than implementing them as
3+
macros. So they can be loaded by dlopen/dlsym in an embedded in Python,
4+
rather than having to reimplement these macros manually. In the non-limited
5+
C API, these constants are still implemented as macros. Patch by Victor
6+
Stinner.

Objects/boolobject.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,3 +225,10 @@ struct _longobject _Py_TrueStruct = {
225225
{ 1 }
226226
}
227227
};
228+
229+
// Stable ABI: export symbols
230+
231+
#undef Py_False
232+
#undef Py_True
233+
PyLongObject *Py_False = _Py_CAST(PyLongObject*, &_Py_FalseStruct);
234+
PyLongObject *Py_True = _Py_CAST(PyLongObject*, &_Py_TrueStruct);

Objects/object.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2970,3 +2970,8 @@ _Py_SetRefcnt(PyObject *ob, Py_ssize_t refcnt)
29702970
{
29712971
Py_SET_REFCNT(ob, refcnt);
29722972
}
2973+
2974+
#undef Py_None
2975+
2976+
// Export the symbol in the stable ABI
2977+
PyObject *Py_None = &_Py_NoneStruct;

Tools/build/stable_abi.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,16 @@ def test_windows_feature_macros(self):
309309
with self.subTest(name):
310310
self.assertEqual(feature_macros[name], value)
311311
312+
def test_constants(self):
313+
process = ctypes_test.pythonapi
314+
def get_object(name):
315+
return ctypes_test.py_object.in_dll(process, name).value
316+
317+
self.assertIs(get_object("Py_None"), None)
318+
self.assertIs(get_object("Py_False"), False)
319+
self.assertIs(get_object("Py_True"), True)
320+
321+
312322
SYMBOL_NAMES = (
313323
'''))
314324
items = manifest.select(

0 commit comments

Comments
 (0)