Skip to content

Commit b6a1512

Browse files
gh-149163: Add PyInitConfig API (PEP 741) to the limited C API
The PyInitConfig API is the modern way for programs embedding Python to initialize the interpreter. However, it was excluded from the limited C API, forcing embedders to use deprecated legacy APIs or build against the full (unstable) C API. Create a new top-level `Include/initconfig.h` header (following the established `pylifecycle.h` / `longobject.h` pattern) that exposes the opaque `PyInitConfig` struct and all 14 associated functions to limited API consumers targeting Python 3.15+. The internal types (PyConfig, PyPreConfig, PyStatus, etc.) remain excluded from the limited API.
1 parent b413bc7 commit b6a1512

9 files changed

Lines changed: 153 additions & 47 deletions

File tree

Doc/c-api/init_config.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ PyInitConfig C API
1414

1515
.. versionadded:: 3.14
1616

17+
.. versionchanged:: 3.15
18+
Added to the :ref:`limited C API <limited-c-api>`.
19+
1720
Python can be initialized with :c:func:`Py_InitializeFromInitConfig`.
1821

1922
The :c:func:`Py_RunMain` function can be used to write a customized Python

Doc/data/stable_abi.dat

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Doc/whatsnew/3.15.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2075,6 +2075,10 @@ Changed C APIs
20752075
for ``NULL`` should be updated to call :c:macro:`PyDateTime_IMPORT` instead.
20762076
(Contributed by Kumar Aditya in :gh:`141563`.)
20772077

2078+
* The :ref:`PyInitConfig API <pyinitconfig_api>` (:pep:`741`) is now part of
2079+
the :ref:`limited C API <limited-c-api>`.
2080+
(Contributed by in :gh:`149163`.)
2081+
20782082
Porting to Python 3.15
20792083
----------------------
20802084

Include/Python.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ __pragma(warning(disable: 4201))
112112
#include "sliceobject.h"
113113
#include "cpython/cellobject.h"
114114
#include "iterobject.h"
115-
#include "cpython/initconfig.h"
115+
#include "initconfig.h"
116116
#include "pystate.h"
117117
#include "cpython/genobject.h"
118118
#include "descrobject.h"

Include/cpython/initconfig.h

Lines changed: 4 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#ifndef Py_PYCORECONFIG_H
22
#define Py_PYCORECONFIG_H
3-
#ifndef Py_LIMITED_API
3+
#ifndef Py_CPYTHON_INITCONFIG_H
4+
# error "this header file must not be included directly"
5+
#endif
6+
47
#ifdef __cplusplus
58
extern "C" {
69
#endif
@@ -284,52 +287,7 @@ PyAPI_FUNC(int) PyConfig_Set(const char *name, PyObject *value);
284287
PyAPI_FUNC(void) Py_GetArgcArgv(int *argc, wchar_t ***argv);
285288

286289

287-
// --- PyInitConfig ---------------------------------------------------------
288-
289-
typedef struct PyInitConfig PyInitConfig;
290-
291-
PyAPI_FUNC(PyInitConfig*) PyInitConfig_Create(void);
292-
PyAPI_FUNC(void) PyInitConfig_Free(PyInitConfig *config);
293-
294-
PyAPI_FUNC(int) PyInitConfig_GetError(PyInitConfig* config,
295-
const char **err_msg);
296-
PyAPI_FUNC(int) PyInitConfig_GetExitCode(PyInitConfig* config,
297-
int *exitcode);
298-
299-
PyAPI_FUNC(int) PyInitConfig_HasOption(PyInitConfig *config,
300-
const char *name);
301-
PyAPI_FUNC(int) PyInitConfig_GetInt(PyInitConfig *config,
302-
const char *name,
303-
int64_t *value);
304-
PyAPI_FUNC(int) PyInitConfig_GetStr(PyInitConfig *config,
305-
const char *name,
306-
char **value);
307-
PyAPI_FUNC(int) PyInitConfig_GetStrList(PyInitConfig *config,
308-
const char *name,
309-
size_t *length,
310-
char ***items);
311-
PyAPI_FUNC(void) PyInitConfig_FreeStrList(size_t length, char **items);
312-
313-
PyAPI_FUNC(int) PyInitConfig_SetInt(PyInitConfig *config,
314-
const char *name,
315-
int64_t value);
316-
PyAPI_FUNC(int) PyInitConfig_SetStr(PyInitConfig *config,
317-
const char *name,
318-
const char *value);
319-
PyAPI_FUNC(int) PyInitConfig_SetStrList(PyInitConfig *config,
320-
const char *name,
321-
size_t length,
322-
char * const *items);
323-
324-
PyAPI_FUNC(int) PyInitConfig_AddModule(PyInitConfig *config,
325-
const char *name,
326-
PyObject* (*initfunc)(void));
327-
328-
PyAPI_FUNC(int) Py_InitializeFromInitConfig(PyInitConfig *config);
329-
330-
331290
#ifdef __cplusplus
332291
}
333292
#endif
334-
#endif /* !Py_LIMITED_API */
335293
#endif /* !Py_PYCORECONFIG_H */

Include/initconfig.h

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#ifndef Py_INITCONFIG_H
2+
#define Py_INITCONFIG_H
3+
#ifdef __cplusplus
4+
extern "C" {
5+
#endif
6+
7+
8+
// --- PyInitConfig (PEP 741) -----------------------------------------------
9+
10+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030f0000
11+
12+
typedef struct PyInitConfig PyInitConfig;
13+
14+
PyAPI_FUNC(PyInitConfig*) PyInitConfig_Create(void);
15+
PyAPI_FUNC(void) PyInitConfig_Free(PyInitConfig *config);
16+
17+
PyAPI_FUNC(int) PyInitConfig_GetError(PyInitConfig* config,
18+
const char **err_msg);
19+
PyAPI_FUNC(int) PyInitConfig_GetExitCode(PyInitConfig* config,
20+
int *exitcode);
21+
22+
PyAPI_FUNC(int) PyInitConfig_HasOption(PyInitConfig *config,
23+
const char *name);
24+
PyAPI_FUNC(int) PyInitConfig_GetInt(PyInitConfig *config,
25+
const char *name,
26+
int64_t *value);
27+
PyAPI_FUNC(int) PyInitConfig_GetStr(PyInitConfig *config,
28+
const char *name,
29+
char **value);
30+
PyAPI_FUNC(int) PyInitConfig_GetStrList(PyInitConfig *config,
31+
const char *name,
32+
size_t *length,
33+
char ***items);
34+
PyAPI_FUNC(void) PyInitConfig_FreeStrList(size_t length, char **items);
35+
36+
PyAPI_FUNC(int) PyInitConfig_SetInt(PyInitConfig *config,
37+
const char *name,
38+
int64_t value);
39+
PyAPI_FUNC(int) PyInitConfig_SetStr(PyInitConfig *config,
40+
const char *name,
41+
const char *value);
42+
PyAPI_FUNC(int) PyInitConfig_SetStrList(PyInitConfig *config,
43+
const char *name,
44+
size_t length,
45+
char * const *items);
46+
47+
PyAPI_FUNC(int) PyInitConfig_AddModule(PyInitConfig *config,
48+
const char *name,
49+
PyObject* (*initfunc)(void));
50+
51+
PyAPI_FUNC(int) Py_InitializeFromInitConfig(PyInitConfig *config);
52+
53+
#endif
54+
55+
#ifndef Py_LIMITED_API
56+
# define Py_CPYTHON_INITCONFIG_H
57+
# include "cpython/initconfig.h"
58+
# undef Py_CPYTHON_INITCONFIG_H
59+
#endif
60+
61+
#ifdef __cplusplus
62+
}
63+
#endif
64+
#endif /* !Py_INITCONFIG_H */

Lib/test/test_stable_abi_ctypes.py

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Misc/stable_abi.toml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2715,3 +2715,37 @@
27152715
# Note: The `_reserved` member of this struct is for interal use only.
27162716
# (The definition of 'full-abi' was clarified when this entry was added.)
27172717
struct_abi_kind = 'full-abi'
2718+
2719+
# PEP 741: Python Configuration C API -- added to limited API.
2720+
2721+
[struct.PyInitConfig]
2722+
added = '3.15'
2723+
struct_abi_kind = 'opaque'
2724+
[function.PyInitConfig_Create]
2725+
added = '3.15'
2726+
[function.PyInitConfig_Free]
2727+
added = '3.15'
2728+
[function.PyInitConfig_GetError]
2729+
added = '3.15'
2730+
[function.PyInitConfig_GetExitCode]
2731+
added = '3.15'
2732+
[function.PyInitConfig_HasOption]
2733+
added = '3.15'
2734+
[function.PyInitConfig_GetInt]
2735+
added = '3.15'
2736+
[function.PyInitConfig_GetStr]
2737+
added = '3.15'
2738+
[function.PyInitConfig_GetStrList]
2739+
added = '3.15'
2740+
[function.PyInitConfig_FreeStrList]
2741+
added = '3.15'
2742+
[function.PyInitConfig_SetInt]
2743+
added = '3.15'
2744+
[function.PyInitConfig_SetStr]
2745+
added = '3.15'
2746+
[function.PyInitConfig_SetStrList]
2747+
added = '3.15'
2748+
[function.PyInitConfig_AddModule]
2749+
added = '3.15'
2750+
[function.Py_InitializeFromInitConfig]
2751+
added = '3.15'

PC/python3dll.c

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)