@@ -19,6 +19,7 @@ extern "C" {
19
19
#endif
20
20
21
21
#include < Python.h>
22
+ #include < stddef.h> // offsetof()
22
23
23
24
// Python 3.11.0b4 added PyFrame_Back() to Python.h
24
25
#if PY_VERSION_HEX < 0x030b00B4 && !defined(PYPY_VERSION)
@@ -1974,6 +1975,229 @@ int Py_fclose(FILE *file)
1974
1975
#endif
1975
1976
1976
1977
1978
+ #if 0x03090000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030E0000 && !defined(PYPY_VERSION)
1979
+ static inline PyObject*
1980
+ PyConfig_Get (const char *name)
1981
+ {
1982
+ typedef enum {
1983
+ _PyConfig_MEMBER_INT,
1984
+ _PyConfig_MEMBER_UINT,
1985
+ _PyConfig_MEMBER_ULONG,
1986
+ _PyConfig_MEMBER_BOOL,
1987
+ _PyConfig_MEMBER_WSTR,
1988
+ _PyConfig_MEMBER_WSTR_OPT,
1989
+ _PyConfig_MEMBER_WSTR_LIST,
1990
+ } PyConfigMemberType;
1991
+
1992
+ typedef struct {
1993
+ const char *name;
1994
+ size_t offset;
1995
+ PyConfigMemberType type;
1996
+ const char *sys_attr;
1997
+ } PyConfigSpec;
1998
+
1999
+ #define PYTHONCAPI_COMPAT_SPEC (MEMBER, TYPE, sys_attr ) \
2000
+ {#MEMBER, offsetof (PyConfig, MEMBER), \
2001
+ _PyConfig_MEMBER_##TYPE, sys_attr}
2002
+
2003
+ static const PyConfigSpec config_spec[] = {
2004
+ PYTHONCAPI_COMPAT_SPEC (argv, WSTR_LIST, " argv" ),
2005
+ PYTHONCAPI_COMPAT_SPEC (base_exec_prefix, WSTR_OPT, " base_exec_prefix" ),
2006
+ PYTHONCAPI_COMPAT_SPEC (base_executable, WSTR_OPT, " _base_executable" ),
2007
+ PYTHONCAPI_COMPAT_SPEC (base_prefix, WSTR_OPT, " base_prefix" ),
2008
+ PYTHONCAPI_COMPAT_SPEC (bytes_warning, UINT, _Py_NULL),
2009
+ PYTHONCAPI_COMPAT_SPEC (exec_prefix, WSTR_OPT, " exec_prefix" ),
2010
+ PYTHONCAPI_COMPAT_SPEC (executable, WSTR_OPT, " executable" ),
2011
+ PYTHONCAPI_COMPAT_SPEC (inspect, BOOL, _Py_NULL),
2012
+ #if 0x030C0000 <= PY_VERSION_HEX
2013
+ PYTHONCAPI_COMPAT_SPEC (int_max_str_digits, UINT, _Py_NULL),
2014
+ #endif
2015
+ PYTHONCAPI_COMPAT_SPEC (interactive, BOOL, _Py_NULL),
2016
+ PYTHONCAPI_COMPAT_SPEC (module_search_paths, WSTR_LIST, " path" ),
2017
+ PYTHONCAPI_COMPAT_SPEC (optimization_level, UINT, _Py_NULL),
2018
+ PYTHONCAPI_COMPAT_SPEC (parser_debug, BOOL, _Py_NULL),
2019
+ PYTHONCAPI_COMPAT_SPEC (platlibdir, WSTR, " platlibdir" ),
2020
+ PYTHONCAPI_COMPAT_SPEC (prefix, WSTR_OPT, " prefix" ),
2021
+ PYTHONCAPI_COMPAT_SPEC (pycache_prefix, WSTR_OPT, " pycache_prefix" ),
2022
+ PYTHONCAPI_COMPAT_SPEC (quiet, BOOL, _Py_NULL),
2023
+ #if 0x030B0000 <= PY_VERSION_HEX
2024
+ PYTHONCAPI_COMPAT_SPEC (stdlib_dir, WSTR_OPT, " _stdlib_dir" ),
2025
+ #endif
2026
+ PYTHONCAPI_COMPAT_SPEC (use_environment, BOOL, _Py_NULL),
2027
+ PYTHONCAPI_COMPAT_SPEC (verbose, UINT, _Py_NULL),
2028
+ PYTHONCAPI_COMPAT_SPEC (warnoptions, WSTR_LIST, " warnoptions" ),
2029
+ PYTHONCAPI_COMPAT_SPEC (write_bytecode, BOOL, _Py_NULL),
2030
+ PYTHONCAPI_COMPAT_SPEC (xoptions, WSTR_LIST, " _xoptions" ),
2031
+ PYTHONCAPI_COMPAT_SPEC (buffered_stdio, BOOL, _Py_NULL),
2032
+ PYTHONCAPI_COMPAT_SPEC (check_hash_pycs_mode, WSTR, _Py_NULL),
2033
+ #if 0x030B0000 <= PY_VERSION_HEX
2034
+ PYTHONCAPI_COMPAT_SPEC (code_debug_ranges, BOOL, _Py_NULL),
2035
+ #endif
2036
+ PYTHONCAPI_COMPAT_SPEC (configure_c_stdio, BOOL, _Py_NULL),
2037
+ #if 0x030D0000 <= PY_VERSION_HEX
2038
+ PYTHONCAPI_COMPAT_SPEC (cpu_count, INT, _Py_NULL),
2039
+ #endif
2040
+ PYTHONCAPI_COMPAT_SPEC (dev_mode, BOOL, _Py_NULL),
2041
+ PYTHONCAPI_COMPAT_SPEC (dump_refs, BOOL, _Py_NULL),
2042
+ #if 0x030B0000 <= PY_VERSION_HEX
2043
+ PYTHONCAPI_COMPAT_SPEC (dump_refs_file, WSTR_OPT, _Py_NULL),
2044
+ #endif
2045
+ #ifdef Py_GIL_DISABLED
2046
+ PYTHONCAPI_COMPAT_SPEC (enable_gil, INT, _Py_NULL),
2047
+ #endif
2048
+ PYTHONCAPI_COMPAT_SPEC (faulthandler, BOOL, _Py_NULL),
2049
+ PYTHONCAPI_COMPAT_SPEC (filesystem_encoding, WSTR, _Py_NULL),
2050
+ PYTHONCAPI_COMPAT_SPEC (filesystem_errors, WSTR, _Py_NULL),
2051
+ PYTHONCAPI_COMPAT_SPEC (hash_seed, ULONG, _Py_NULL),
2052
+ PYTHONCAPI_COMPAT_SPEC (home, WSTR_OPT, _Py_NULL),
2053
+ PYTHONCAPI_COMPAT_SPEC (import_time, BOOL, _Py_NULL),
2054
+ PYTHONCAPI_COMPAT_SPEC (install_signal_handlers, BOOL, _Py_NULL),
2055
+ PYTHONCAPI_COMPAT_SPEC (isolated, BOOL, _Py_NULL),
2056
+ #ifdef MS_WINDOWS
2057
+ PYTHONCAPI_COMPAT_SPEC (legacy_windows_stdio, BOOL, _Py_NULL),
2058
+ #endif
2059
+ PYTHONCAPI_COMPAT_SPEC (malloc_stats, BOOL, _Py_NULL),
2060
+ #if 0x030A0000 <= PY_VERSION_HEX
2061
+ PYTHONCAPI_COMPAT_SPEC (orig_argv, WSTR_LIST, " orig_argv" ),
2062
+ #endif
2063
+ PYTHONCAPI_COMPAT_SPEC (parse_argv, BOOL, _Py_NULL),
2064
+ PYTHONCAPI_COMPAT_SPEC (pathconfig_warnings, BOOL, _Py_NULL),
2065
+ #if 0x030C0000 <= PY_VERSION_HEX
2066
+ PYTHONCAPI_COMPAT_SPEC (perf_profiling, UINT, _Py_NULL),
2067
+ #endif
2068
+ PYTHONCAPI_COMPAT_SPEC (program_name, WSTR, _Py_NULL),
2069
+ PYTHONCAPI_COMPAT_SPEC (run_command, WSTR_OPT, _Py_NULL),
2070
+ PYTHONCAPI_COMPAT_SPEC (run_filename, WSTR_OPT, _Py_NULL),
2071
+ PYTHONCAPI_COMPAT_SPEC (run_module, WSTR_OPT, _Py_NULL),
2072
+ #if 0x030B0000 <= PY_VERSION_HEX
2073
+ PYTHONCAPI_COMPAT_SPEC (safe_path, BOOL, _Py_NULL),
2074
+ #endif
2075
+ PYTHONCAPI_COMPAT_SPEC (show_ref_count, BOOL, _Py_NULL),
2076
+ PYTHONCAPI_COMPAT_SPEC (site_import, BOOL, _Py_NULL),
2077
+ PYTHONCAPI_COMPAT_SPEC (skip_source_first_line, BOOL, _Py_NULL),
2078
+ PYTHONCAPI_COMPAT_SPEC (stdio_encoding, WSTR, _Py_NULL),
2079
+ PYTHONCAPI_COMPAT_SPEC (stdio_errors, WSTR, _Py_NULL),
2080
+ PYTHONCAPI_COMPAT_SPEC (tracemalloc, UINT, _Py_NULL),
2081
+ #if 0x030B0000 <= PY_VERSION_HEX
2082
+ PYTHONCAPI_COMPAT_SPEC (use_frozen_modules, BOOL, _Py_NULL),
2083
+ #endif
2084
+ PYTHONCAPI_COMPAT_SPEC (use_hash_seed, BOOL, _Py_NULL),
2085
+ #if 0x030D0000 <= PY_VERSION_HEX && defined(__APPLE__)
2086
+ PYTHONCAPI_COMPAT_SPEC (use_system_logger, BOOL, _Py_NULL),
2087
+ #endif
2088
+ PYTHONCAPI_COMPAT_SPEC (user_site_directory, BOOL, _Py_NULL),
2089
+ #if 0x030A0000 <= PY_VERSION_HEX
2090
+ PYTHONCAPI_COMPAT_SPEC (warn_default_encoding, BOOL, _Py_NULL),
2091
+ #endif
2092
+ };
2093
+
2094
+ #undef PYTHONCAPI_COMPAT_SPEC
2095
+
2096
+ const PyConfigSpec *spec;
2097
+ int found = 0 ;
2098
+ for (size_t i=0 ; i < Py_ARRAY_LENGTH (config_spec); i++) {
2099
+ spec = &config_spec[i];
2100
+ if (strcmp (spec->name , name) == 0 ) {
2101
+ found = 1 ;
2102
+ break ;
2103
+ }
2104
+ }
2105
+ if (found) {
2106
+ if (spec->sys_attr != NULL ) {
2107
+ PyObject *value = PySys_GetObject (spec->sys_attr );
2108
+ if (value == NULL ) {
2109
+ PyErr_Format (PyExc_RuntimeError, " lost sys.%s" , spec->sys_attr );
2110
+ return NULL ;
2111
+ }
2112
+ return Py_NewRef (value);
2113
+ }
2114
+
2115
+ extern const PyConfig* _Py_GetConfig (void );
2116
+ const PyConfig *config = _Py_GetConfig ();
2117
+ void *member = (char *)config + spec->offset ;
2118
+ switch (spec->type ) {
2119
+ case _PyConfig_MEMBER_INT:
2120
+ case _PyConfig_MEMBER_UINT:
2121
+ {
2122
+ int value = *(int *)member;
2123
+ return PyLong_FromLong (value);
2124
+ }
2125
+ case _PyConfig_MEMBER_BOOL:
2126
+ {
2127
+ int value = *(int *)member;
2128
+ return PyBool_FromLong (value != 0 );
2129
+ }
2130
+ case _PyConfig_MEMBER_ULONG:
2131
+ {
2132
+ unsigned long value = *(unsigned long *)member;
2133
+ return PyLong_FromUnsignedLong (value);
2134
+ }
2135
+ case _PyConfig_MEMBER_WSTR:
2136
+ case _PyConfig_MEMBER_WSTR_OPT:
2137
+ {
2138
+ wchar_t *wstr = *(wchar_t **)member;
2139
+ if (wstr != NULL ) {
2140
+ return PyUnicode_FromWideChar (wstr, -1 );
2141
+ }
2142
+ else {
2143
+ return Py_NewRef (Py_None);
2144
+ }
2145
+ }
2146
+ case _PyConfig_MEMBER_WSTR_LIST:
2147
+ {
2148
+ const PyWideStringList *list = (const PyWideStringList *)member;
2149
+ PyObject *tuple = PyTuple_New (list->length );
2150
+ if (tuple == NULL ) {
2151
+ return NULL ;
2152
+ }
2153
+
2154
+ for (Py_ssize_t i = 0 ; i < list->length ; i++) {
2155
+ PyObject *item = PyUnicode_FromWideChar (list->items [i], -1 );
2156
+ if (item == NULL ) {
2157
+ Py_DECREF (tuple);
2158
+ return NULL ;
2159
+ }
2160
+ PyTuple_SET_ITEM (tuple, i, item);
2161
+ }
2162
+ return tuple;
2163
+ }
2164
+ default :
2165
+ Py_UNREACHABLE ();
2166
+ }
2167
+ }
2168
+
2169
+ PyErr_Format (PyExc_ValueError, " unknown config option name: %s" , name);
2170
+ return NULL ;
2171
+ }
2172
+
2173
+ static inline int
2174
+ PyConfig_GetInt (const char *name, int *value)
2175
+ {
2176
+ PyObject *obj = PyConfig_Get (name);
2177
+ if (obj == NULL ) {
2178
+ return -1 ;
2179
+ }
2180
+
2181
+ if (!PyLong_Check (obj)) {
2182
+ Py_DECREF (obj);
2183
+ PyErr_Format (PyExc_TypeError, " config option %s is not an int" , name);
2184
+ return -1 ;
2185
+ }
2186
+
2187
+ int as_int = PyLong_AsInt (obj);
2188
+ Py_DECREF (obj);
2189
+ if (as_int == -1 && PyErr_Occurred ()) {
2190
+ PyErr_Format (PyExc_OverflowError,
2191
+ " config option %s value does not fit into a C int" , name);
2192
+ return -1 ;
2193
+ }
2194
+
2195
+ *value = as_int;
2196
+ return 0 ;
2197
+ }
2198
+ #endif // PY_VERSION_HEX > 0x03090000 && !defined(PYPY_VERSION)
2199
+
2200
+
1977
2201
#ifdef __cplusplus
1978
2202
}
1979
2203
#endif
0 commit comments