| 
									
										
										
										
											2023-10-30 16:53:10 -06:00
										 |  |  | #ifndef Py_INTERNAL_CROSSINTERP_H
 | 
					
						
							|  |  |  | #define Py_INTERNAL_CROSSINTERP_H
 | 
					
						
							|  |  |  | #ifdef __cplusplus
 | 
					
						
							|  |  |  | extern "C" { | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef Py_BUILD_CORE
 | 
					
						
							|  |  |  | #  error "this header requires Py_BUILD_CORE define"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  | #include "pycore_pyerrors.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-11 14:49:41 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  | /**************/ | 
					
						
							|  |  |  | /* exceptions */ | 
					
						
							|  |  |  | /**************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyAPI_DATA(PyObject *) PyExc_InterpreterError; | 
					
						
							|  |  |  | PyAPI_DATA(PyObject *) PyExc_InterpreterNotFoundError; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-30 16:53:10 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | /***************************/ | 
					
						
							|  |  |  | /* cross-interpreter calls */ | 
					
						
							|  |  |  | /***************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef int (*_Py_simple_func)(void *); | 
					
						
							|  |  |  | extern int _Py_CallInInterpreter( | 
					
						
							|  |  |  |     PyInterpreterState *interp, | 
					
						
							|  |  |  |     _Py_simple_func func, | 
					
						
							|  |  |  |     void *arg); | 
					
						
							|  |  |  | extern int _Py_CallInInterpreterAndRawFree( | 
					
						
							|  |  |  |     PyInterpreterState *interp, | 
					
						
							|  |  |  |     _Py_simple_func func, | 
					
						
							|  |  |  |     void *arg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**************************/ | 
					
						
							|  |  |  | /* cross-interpreter data */ | 
					
						
							|  |  |  | /**************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-11 15:58:46 -07:00
										 |  |  | typedef struct _xidata _PyXIData_t; | 
					
						
							|  |  |  | typedef PyObject *(*xid_newobjfunc)(_PyXIData_t *); | 
					
						
							| 
									
										
										
										
											2023-10-30 16:53:10 -06:00
										 |  |  | typedef void (*xid_freefunc)(void *); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-07 09:32:42 -07:00
										 |  |  | // _PyXIData_t is similar to Py_buffer as an effectively
 | 
					
						
							| 
									
										
										
										
											2023-10-30 16:53:10 -06:00
										 |  |  | // opaque struct that holds data outside the object machinery.  This
 | 
					
						
							|  |  |  | // is necessary to pass safely between interpreters in the same process.
 | 
					
						
							| 
									
										
										
										
											2024-11-11 15:58:46 -07:00
										 |  |  | struct _xidata { | 
					
						
							| 
									
										
										
										
											2023-10-30 16:53:10 -06:00
										 |  |  |     // data is the cross-interpreter-safe derivation of a Python object
 | 
					
						
							| 
									
										
										
										
											2024-11-07 09:32:42 -07:00
										 |  |  |     // (see _PyObject_GetXIData).  It will be NULL if the
 | 
					
						
							| 
									
										
										
										
											2023-10-30 16:53:10 -06:00
										 |  |  |     // new_object func (below) encodes the data.
 | 
					
						
							|  |  |  |     void *data; | 
					
						
							|  |  |  |     // obj is the Python object from which the data was derived.  This
 | 
					
						
							|  |  |  |     // is non-NULL only if the data remains bound to the object in some
 | 
					
						
							|  |  |  |     // way, such that the object must be "released" (via a decref) when
 | 
					
						
							|  |  |  |     // the data is released.  In that case the code that sets the field,
 | 
					
						
							| 
									
										
										
										
											2024-11-07 09:32:42 -07:00
										 |  |  |     // likely a registered "xidatafunc", is responsible for
 | 
					
						
							| 
									
										
										
										
											2023-10-30 16:53:10 -06:00
										 |  |  |     // ensuring it owns the reference (i.e. incref).
 | 
					
						
							|  |  |  |     PyObject *obj; | 
					
						
							| 
									
										
										
										
											2025-04-28 11:55:15 -06:00
										 |  |  |     // interpid is the ID of the owning interpreter of the original
 | 
					
						
							| 
									
										
										
										
											2023-10-30 16:53:10 -06:00
										 |  |  |     // object.  It corresponds to the active interpreter when
 | 
					
						
							| 
									
										
										
										
											2024-11-07 09:32:42 -07:00
										 |  |  |     // _PyObject_GetXIData() was called.  This should only
 | 
					
						
							| 
									
										
										
										
											2023-10-30 16:53:10 -06:00
										 |  |  |     // be set by the cross-interpreter machinery.
 | 
					
						
							|  |  |  |     //
 | 
					
						
							|  |  |  |     // We use the ID rather than the PyInterpreterState to avoid issues
 | 
					
						
							|  |  |  |     // with deleted interpreters.  Note that IDs are never re-used, so
 | 
					
						
							|  |  |  |     // each one will always correspond to a specific interpreter
 | 
					
						
							|  |  |  |     // (whether still alive or not).
 | 
					
						
							|  |  |  |     int64_t interpid; | 
					
						
							|  |  |  |     // new_object is a function that returns a new object in the current
 | 
					
						
							|  |  |  |     // interpreter given the data.  The resulting object (a new
 | 
					
						
							|  |  |  |     // reference) will be equivalent to the original object.  This field
 | 
					
						
							|  |  |  |     // is required.
 | 
					
						
							| 
									
										
										
										
											2024-11-11 15:58:46 -07:00
										 |  |  |     xid_newobjfunc new_object; | 
					
						
							| 
									
										
										
										
											2023-10-30 16:53:10 -06:00
										 |  |  |     // free is called when the data is released.  If it is NULL then
 | 
					
						
							|  |  |  |     // nothing will be done to free the data.  For some types this is
 | 
					
						
							|  |  |  |     // okay (e.g. bytes) and for those types this field should be set
 | 
					
						
							|  |  |  |     // to NULL.  However, for most the data was allocated just for
 | 
					
						
							|  |  |  |     // cross-interpreter use, so it must be freed when
 | 
					
						
							| 
									
										
										
										
											2024-11-07 09:32:42 -07:00
										 |  |  |     // _PyXIData_Release is called or the memory will
 | 
					
						
							| 
									
										
										
										
											2023-10-30 16:53:10 -06:00
										 |  |  |     // leak.  In that case, at the very least this field should be set
 | 
					
						
							|  |  |  |     // to PyMem_RawFree (the default if not explicitly set to NULL).
 | 
					
						
							|  |  |  |     // The call will happen with the original interpreter activated.
 | 
					
						
							|  |  |  |     xid_freefunc free; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-07 09:32:42 -07:00
										 |  |  | PyAPI_FUNC(_PyXIData_t *) _PyXIData_New(void); | 
					
						
							|  |  |  | PyAPI_FUNC(void) _PyXIData_Free(_PyXIData_t *data); | 
					
						
							| 
									
										
										
										
											2023-10-30 16:53:10 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-07 09:32:42 -07:00
										 |  |  | #define _PyXIData_DATA(DATA) ((DATA)->data)
 | 
					
						
							|  |  |  | #define _PyXIData_OBJ(DATA) ((DATA)->obj)
 | 
					
						
							|  |  |  | #define _PyXIData_INTERPID(DATA) ((DATA)->interpid)
 | 
					
						
							| 
									
										
										
										
											2024-02-13 14:56:49 -07:00
										 |  |  | // Users should not need getters for "new_object" or "free".
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-30 16:53:10 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* defining cross-interpreter data */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-07 09:32:42 -07:00
										 |  |  | PyAPI_FUNC(void) _PyXIData_Init( | 
					
						
							|  |  |  |         _PyXIData_t *data, | 
					
						
							| 
									
										
										
										
											2023-10-30 16:53:10 -06:00
										 |  |  |         PyInterpreterState *interp, void *shared, PyObject *obj, | 
					
						
							| 
									
										
										
										
											2024-11-11 15:58:46 -07:00
										 |  |  |         xid_newobjfunc new_object); | 
					
						
							| 
									
										
										
										
											2024-11-07 09:32:42 -07:00
										 |  |  | PyAPI_FUNC(int) _PyXIData_InitWithSize( | 
					
						
							|  |  |  |         _PyXIData_t *, | 
					
						
							| 
									
										
										
										
											2023-10-30 16:53:10 -06:00
										 |  |  |         PyInterpreterState *interp, const size_t, PyObject *, | 
					
						
							| 
									
										
										
										
											2024-11-11 15:58:46 -07:00
										 |  |  |         xid_newobjfunc); | 
					
						
							| 
									
										
										
										
											2025-04-28 11:55:15 -06:00
										 |  |  | PyAPI_FUNC(void) _PyXIData_Clear(PyInterpreterState *, _PyXIData_t *); | 
					
						
							| 
									
										
										
										
											2023-10-30 16:53:10 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-13 14:56:49 -07:00
										 |  |  | // Normally the Init* functions are sufficient.  The only time
 | 
					
						
							|  |  |  | // additional initialization might be needed is to set the "free" func,
 | 
					
						
							|  |  |  | // though that should be infrequent.
 | 
					
						
							| 
									
										
										
										
											2024-11-07 09:32:42 -07:00
										 |  |  | #define _PyXIData_SET_FREE(DATA, FUNC) \
 | 
					
						
							| 
									
										
										
										
											2024-02-13 14:56:49 -07:00
										 |  |  |     do { \ | 
					
						
							|  |  |  |         (DATA)->free = (FUNC); \ | 
					
						
							|  |  |  |     } while (0) | 
					
						
							| 
									
										
										
										
											2025-04-28 12:52:36 -06:00
										 |  |  | #define _PyXIData_CHECK_FREE(DATA, FUNC) \
 | 
					
						
							|  |  |  |     ((DATA)->free == (FUNC)) | 
					
						
							| 
									
										
										
										
											2024-02-13 14:56:49 -07:00
										 |  |  | // Additionally, some shareable types are essentially light wrappers
 | 
					
						
							| 
									
										
										
										
											2024-11-07 09:32:42 -07:00
										 |  |  | // around other shareable types.  The xidatafunc of the wrapper
 | 
					
						
							| 
									
										
										
										
											2024-02-13 14:56:49 -07:00
										 |  |  | // can often be implemented by calling the wrapped object's
 | 
					
						
							| 
									
										
										
										
											2024-11-07 09:32:42 -07:00
										 |  |  | // xidatafunc and then changing the "new_object" function.
 | 
					
						
							|  |  |  | // We have _PyXIData_SET_NEW_OBJECT() here for that,
 | 
					
						
							| 
									
										
										
										
											2024-02-13 14:56:49 -07:00
										 |  |  | // but might be better to have a function like
 | 
					
						
							| 
									
										
										
										
											2024-11-07 09:32:42 -07:00
										 |  |  | // _PyXIData_AdaptToWrapper() instead.
 | 
					
						
							|  |  |  | #define _PyXIData_SET_NEW_OBJECT(DATA, FUNC) \
 | 
					
						
							| 
									
										
										
										
											2024-02-13 14:56:49 -07:00
										 |  |  |     do { \ | 
					
						
							|  |  |  |         (DATA)->new_object = (FUNC); \ | 
					
						
							|  |  |  |     } while (0) | 
					
						
							| 
									
										
										
										
											2025-04-28 12:52:36 -06:00
										 |  |  | #define _PyXIData_CHECK_NEW_OBJECT(DATA, FUNC) \
 | 
					
						
							|  |  |  |     ((DATA)->new_object == (FUNC)) | 
					
						
							| 
									
										
										
										
											2024-02-13 14:56:49 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-30 16:53:10 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-28 11:55:15 -06:00
										 |  |  | /* getting cross-interpreter data */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef int (*xidatafunc)(PyThreadState *tstate, PyObject *, _PyXIData_t *); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyAPI_FUNC(PyObject *) _PyXIData_GetNotShareableErrorType(PyThreadState *); | 
					
						
							|  |  |  | PyAPI_FUNC(void) _PyXIData_SetNotShareableError(PyThreadState *, const char *); | 
					
						
							|  |  |  | PyAPI_FUNC(void) _PyXIData_FormatNotShareableError( | 
					
						
							|  |  |  |         PyThreadState *, | 
					
						
							|  |  |  |         const char *, | 
					
						
							|  |  |  |         ...); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyAPI_FUNC(xidatafunc) _PyXIData_Lookup( | 
					
						
							|  |  |  |         PyThreadState *, | 
					
						
							|  |  |  |         PyObject *); | 
					
						
							|  |  |  | PyAPI_FUNC(int) _PyObject_CheckXIData( | 
					
						
							|  |  |  |         PyThreadState *, | 
					
						
							|  |  |  |         PyObject *); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyAPI_FUNC(int) _PyObject_GetXIData( | 
					
						
							|  |  |  |         PyThreadState *, | 
					
						
							|  |  |  |         PyObject *, | 
					
						
							|  |  |  |         _PyXIData_t *); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-28 12:52:36 -06:00
										 |  |  | // _PyObject_GetXIData() for bytes
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  |     const char *bytes; | 
					
						
							|  |  |  |     Py_ssize_t len; | 
					
						
							|  |  |  | } _PyBytes_data_t; | 
					
						
							|  |  |  | PyAPI_FUNC(int) _PyBytes_GetData(PyObject *, _PyBytes_data_t *); | 
					
						
							|  |  |  | PyAPI_FUNC(PyObject *) _PyBytes_FromData(_PyBytes_data_t *); | 
					
						
							|  |  |  | PyAPI_FUNC(PyObject *) _PyBytes_FromXIData(_PyXIData_t *); | 
					
						
							|  |  |  | PyAPI_FUNC(int) _PyBytes_GetXIData( | 
					
						
							|  |  |  |         PyThreadState *, | 
					
						
							|  |  |  |         PyObject *, | 
					
						
							|  |  |  |         _PyXIData_t *); | 
					
						
							|  |  |  | PyAPI_FUNC(_PyBytes_data_t *) _PyBytes_GetXIDataWrapped( | 
					
						
							|  |  |  |         PyThreadState *, | 
					
						
							|  |  |  |         PyObject *, | 
					
						
							|  |  |  |         size_t, | 
					
						
							|  |  |  |         xid_newobjfunc, | 
					
						
							|  |  |  |         _PyXIData_t *); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-28 11:55:15 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* using cross-interpreter data */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyAPI_FUNC(PyObject *) _PyXIData_NewObject(_PyXIData_t *); | 
					
						
							|  |  |  | PyAPI_FUNC(int) _PyXIData_Release(_PyXIData_t *); | 
					
						
							|  |  |  | PyAPI_FUNC(int) _PyXIData_ReleaseAndRawFree(_PyXIData_t *); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-30 16:53:10 -06:00
										 |  |  | /* cross-interpreter data registry */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-07 09:32:42 -07:00
										 |  |  | #define Py_CORE_CROSSINTERP_DATA_REGISTRY_H
 | 
					
						
							|  |  |  | #include "pycore_crossinterp_data_registry.h"
 | 
					
						
							|  |  |  | #undef Py_CORE_CROSSINTERP_DATA_REGISTRY_H
 | 
					
						
							| 
									
										
										
										
											2023-10-30 16:53:10 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  | /*****************************/ | 
					
						
							|  |  |  | /* runtime state & lifecycle */ | 
					
						
							|  |  |  | /*****************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-25 14:43:38 -06:00
										 |  |  | typedef struct _xid_lookup_state _PyXIData_lookup_t; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-11 15:58:46 -07:00
										 |  |  | typedef struct { | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  |     // builtin types
 | 
					
						
							| 
									
										
										
										
											2024-11-07 09:32:42 -07:00
										 |  |  |     _PyXIData_lookup_t data_lookup; | 
					
						
							| 
									
										
										
										
											2024-11-11 15:58:46 -07:00
										 |  |  | } _PyXI_global_state_t; | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-11 15:58:46 -07:00
										 |  |  | typedef struct { | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  |     // heap types
 | 
					
						
							| 
									
										
										
										
											2024-11-07 09:32:42 -07:00
										 |  |  |     _PyXIData_lookup_t data_lookup; | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-11 14:49:41 -07:00
										 |  |  |     struct xi_exceptions { | 
					
						
							|  |  |  |         // static types
 | 
					
						
							|  |  |  |         PyObject *PyExc_InterpreterError; | 
					
						
							|  |  |  |         PyObject *PyExc_InterpreterNotFoundError; | 
					
						
							|  |  |  |         // heap types
 | 
					
						
							|  |  |  |         PyObject *PyExc_NotShareableError; | 
					
						
							|  |  |  |     } exceptions; | 
					
						
							| 
									
										
										
										
											2024-11-11 15:58:46 -07:00
										 |  |  | } _PyXI_state_t; | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-12 10:41:51 -07:00
										 |  |  | #define _PyXI_GET_GLOBAL_STATE(interp) (&(interp)->runtime->xi)
 | 
					
						
							|  |  |  | #define _PyXI_GET_STATE(interp) (&(interp)->xi)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef Py_BUILD_CORE_MODULE
 | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  | extern PyStatus _PyXI_Init(PyInterpreterState *interp); | 
					
						
							|  |  |  | extern void _PyXI_Fini(PyInterpreterState *interp); | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  | extern PyStatus _PyXI_InitTypes(PyInterpreterState *interp); | 
					
						
							|  |  |  | extern void _PyXI_FiniTypes(PyInterpreterState *interp); | 
					
						
							| 
									
										
										
										
											2024-11-12 10:41:51 -07:00
										 |  |  | #endif  // Py_BUILD_CORE_MODULE
 | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-12 10:41:51 -07:00
										 |  |  | int _Py_xi_global_state_init(_PyXI_global_state_t *); | 
					
						
							|  |  |  | void _Py_xi_global_state_fini(_PyXI_global_state_t *); | 
					
						
							|  |  |  | int _Py_xi_state_init(_PyXI_state_t *, PyInterpreterState *); | 
					
						
							|  |  |  | void _Py_xi_state_fini(_PyXI_state_t *, PyInterpreterState *); | 
					
						
							| 
									
										
										
										
											2024-02-13 14:56:49 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | /***************************/ | 
					
						
							|  |  |  | /* short-term data sharing */ | 
					
						
							|  |  |  | /***************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-06 11:09:22 -07:00
										 |  |  | // Ultimately we'd like to preserve enough information about the
 | 
					
						
							|  |  |  | // exception and traceback that we could re-constitute (or at least
 | 
					
						
							|  |  |  | // simulate, a la traceback.TracebackException), and even chain, a copy
 | 
					
						
							|  |  |  | // of the exception in the calling interpreter.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct _excinfo { | 
					
						
							| 
									
										
										
										
											2023-11-22 17:55:00 -07:00
										 |  |  |     struct _excinfo_type { | 
					
						
							|  |  |  |         PyTypeObject *builtin; | 
					
						
							|  |  |  |         const char *name; | 
					
						
							|  |  |  |         const char *qualname; | 
					
						
							|  |  |  |         const char *module; | 
					
						
							|  |  |  |     } type; | 
					
						
							| 
									
										
										
										
											2023-11-06 11:09:22 -07:00
										 |  |  |     const char *msg; | 
					
						
							| 
									
										
										
										
											2023-12-12 17:31:30 -07:00
										 |  |  |     const char *errdisplay; | 
					
						
							| 
									
										
										
										
											2023-11-22 17:55:00 -07:00
										 |  |  | } _PyXI_excinfo; | 
					
						
							| 
									
										
										
										
											2023-11-06 11:09:22 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-10 18:37:01 -06:00
										 |  |  | PyAPI_FUNC(int) _PyXI_InitExcInfo(_PyXI_excinfo *info, PyObject *exc); | 
					
						
							|  |  |  | PyAPI_FUNC(PyObject *) _PyXI_FormatExcInfo(_PyXI_excinfo *info); | 
					
						
							|  |  |  | PyAPI_FUNC(PyObject *) _PyXI_ExcInfoAsObject(_PyXI_excinfo *info); | 
					
						
							|  |  |  | PyAPI_FUNC(void) _PyXI_ClearExcInfo(_PyXI_excinfo *info); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-06 11:09:22 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  | typedef enum error_code { | 
					
						
							|  |  |  |     _PyXI_ERR_NO_ERROR = 0, | 
					
						
							|  |  |  |     _PyXI_ERR_UNCAUGHT_EXCEPTION = -1, | 
					
						
							|  |  |  |     _PyXI_ERR_OTHER = -2, | 
					
						
							|  |  |  |     _PyXI_ERR_NO_MEMORY = -3, | 
					
						
							|  |  |  |     _PyXI_ERR_ALREADY_RUNNING = -4, | 
					
						
							|  |  |  |     _PyXI_ERR_MAIN_NS_FAILURE = -5, | 
					
						
							|  |  |  |     _PyXI_ERR_APPLY_NS_FAILURE = -6, | 
					
						
							|  |  |  |     _PyXI_ERR_NOT_SHAREABLE = -7, | 
					
						
							|  |  |  | } _PyXI_errcode; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct _sharedexception { | 
					
						
							|  |  |  |     // The originating interpreter.
 | 
					
						
							|  |  |  |     PyInterpreterState *interp; | 
					
						
							|  |  |  |     // The kind of error to propagate.
 | 
					
						
							|  |  |  |     _PyXI_errcode code; | 
					
						
							|  |  |  |     // The exception information to propagate, if applicable.
 | 
					
						
							| 
									
										
										
										
											2023-11-22 17:55:00 -07:00
										 |  |  |     // This is populated only for some error codes,
 | 
					
						
							|  |  |  |     // but always for _PyXI_ERR_UNCAUGHT_EXCEPTION.
 | 
					
						
							|  |  |  |     _PyXI_excinfo uncaught; | 
					
						
							|  |  |  | } _PyXI_error; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyAPI_FUNC(PyObject *) _PyXI_ApplyError(_PyXI_error *err); | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct xi_session _PyXI_session; | 
					
						
							|  |  |  | typedef struct _sharedns _PyXI_namespace; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyAPI_FUNC(void) _PyXI_FreeNamespace(_PyXI_namespace *ns); | 
					
						
							|  |  |  | PyAPI_FUNC(_PyXI_namespace *) _PyXI_NamespaceFromNames(PyObject *names); | 
					
						
							|  |  |  | PyAPI_FUNC(int) _PyXI_FillNamespaceFromDict( | 
					
						
							|  |  |  |     _PyXI_namespace *ns, | 
					
						
							|  |  |  |     PyObject *nsobj, | 
					
						
							|  |  |  |     _PyXI_session *session); | 
					
						
							|  |  |  | PyAPI_FUNC(int) _PyXI_ApplyNamespace( | 
					
						
							|  |  |  |     _PyXI_namespace *ns, | 
					
						
							|  |  |  |     PyObject *nsobj, | 
					
						
							|  |  |  |     PyObject *dflt); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // A cross-interpreter session involves entering an interpreter
 | 
					
						
							|  |  |  | // (_PyXI_Enter()), doing some work with it, and finally exiting
 | 
					
						
							|  |  |  | // that interpreter (_PyXI_Exit()).
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // At the boundaries of the session, both entering and exiting,
 | 
					
						
							|  |  |  | // data may be exchanged between the previous interpreter and the
 | 
					
						
							|  |  |  | // target one in a thread-safe way that does not violate the
 | 
					
						
							|  |  |  | // isolation between interpreters.  This includes setting objects
 | 
					
						
							|  |  |  | // in the target's __main__ module on the way in, and capturing
 | 
					
						
							|  |  |  | // uncaught exceptions on the way out.
 | 
					
						
							|  |  |  | struct xi_session { | 
					
						
							|  |  |  |     // Once a session has been entered, this is the tstate that was
 | 
					
						
							|  |  |  |     // current before the session.  If it is different from cur_tstate
 | 
					
						
							|  |  |  |     // then we must have switched interpreters.  Either way, this will
 | 
					
						
							|  |  |  |     // be the current tstate once we exit the session.
 | 
					
						
							|  |  |  |     PyThreadState *prev_tstate; | 
					
						
							|  |  |  |     // Once a session has been entered, this is the current tstate.
 | 
					
						
							|  |  |  |     // It must be current when the session exits.
 | 
					
						
							|  |  |  |     PyThreadState *init_tstate; | 
					
						
							|  |  |  |     // This is true if init_tstate needs cleanup during exit.
 | 
					
						
							|  |  |  |     int own_init_tstate; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // This is true if, while entering the session, init_thread took
 | 
					
						
							|  |  |  |     // "ownership" of the interpreter's __main__ module.  This means
 | 
					
						
							|  |  |  |     // it is the only thread that is allowed to run code there.
 | 
					
						
							|  |  |  |     // (Caveat: for now, users may still run exec() against the
 | 
					
						
							|  |  |  |     // __main__ module's dict, though that isn't advisable.)
 | 
					
						
							|  |  |  |     int running; | 
					
						
							|  |  |  |     // This is a cached reference to the __dict__ of the entered
 | 
					
						
							|  |  |  |     // interpreter's __main__ module.  It is looked up when at the
 | 
					
						
							|  |  |  |     // beginning of the session as a convenience.
 | 
					
						
							|  |  |  |     PyObject *main_ns; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // This is set if the interpreter is entered and raised an exception
 | 
					
						
							|  |  |  |     // that needs to be handled in some special way during exit.
 | 
					
						
							| 
									
										
										
										
											2023-11-22 17:55:00 -07:00
										 |  |  |     _PyXI_errcode *error_override; | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  |     // This is set if exit captured an exception to propagate.
 | 
					
						
							| 
									
										
										
										
											2023-11-22 17:55:00 -07:00
										 |  |  |     _PyXI_error *error; | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // -- pre-allocated memory --
 | 
					
						
							| 
									
										
										
										
											2023-11-22 17:55:00 -07:00
										 |  |  |     _PyXI_error _error; | 
					
						
							|  |  |  |     _PyXI_errcode _error_override; | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyAPI_FUNC(int) _PyXI_Enter( | 
					
						
							|  |  |  |     _PyXI_session *session, | 
					
						
							|  |  |  |     PyInterpreterState *interp, | 
					
						
							|  |  |  |     PyObject *nsupdates); | 
					
						
							|  |  |  | PyAPI_FUNC(void) _PyXI_Exit(_PyXI_session *session); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-22 17:55:00 -07:00
										 |  |  | PyAPI_FUNC(PyObject *) _PyXI_ApplyCapturedException(_PyXI_session *session); | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  | PyAPI_FUNC(int) _PyXI_HasCapturedException(_PyXI_session *session); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-10 18:37:01 -06:00
										 |  |  | /*************/ | 
					
						
							|  |  |  | /* other API */ | 
					
						
							|  |  |  | /*************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Export for _testinternalcapi shared extension
 | 
					
						
							|  |  |  | PyAPI_FUNC(PyInterpreterState *) _PyXI_NewInterpreter( | 
					
						
							|  |  |  |     PyInterpreterConfig *config, | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     long *maybe_whence, | 
					
						
							| 
									
										
										
										
											2024-04-10 18:37:01 -06:00
										 |  |  |     PyThreadState **p_tstate, | 
					
						
							|  |  |  |     PyThreadState **p_save_tstate); | 
					
						
							|  |  |  | PyAPI_FUNC(void) _PyXI_EndInterpreter( | 
					
						
							|  |  |  |     PyInterpreterState *interp, | 
					
						
							|  |  |  |     PyThreadState *tstate, | 
					
						
							|  |  |  |     PyThreadState **p_save_tstate); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-30 16:53:10 -06:00
										 |  |  | #ifdef __cplusplus
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #endif /* !Py_INTERNAL_CROSSINTERP_H */
 |