Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
pycore_crossinterp.h407 linesDownload Raw Back to internal
1#ifndef Py_INTERNAL_CROSSINTERP_H2#define Py_INTERNAL_CROSSINTERP_H3#ifdef __cplusplus4extern "C" {5#endif6 7#ifndef Py_BUILD_CORE8#  error "this header requires Py_BUILD_CORE define"9#endif10 11#include "pycore_pyerrors.h"12 13 14/**************/15/* exceptions */16/**************/17 18PyAPI_DATA(PyObject *) PyExc_InterpreterError;19PyAPI_DATA(PyObject *) PyExc_InterpreterNotFoundError;20 21 22/***************************/23/* cross-interpreter calls */24/***************************/25 26typedef int (*_Py_simple_func)(void *);27extern int _Py_CallInInterpreter(28    PyInterpreterState *interp,29    _Py_simple_func func,30    void *arg);31extern int _Py_CallInInterpreterAndRawFree(32    PyInterpreterState *interp,33    _Py_simple_func func,34    void *arg);35 36 37/**************************/38/* cross-interpreter data */39/**************************/40 41typedef struct _xidata _PyXIData_t;42typedef PyObject *(*xid_newobjfunc)(_PyXIData_t *);43typedef void (*xid_freefunc)(void *);44 45// _PyXIData_t is similar to Py_buffer as an effectively46// opaque struct that holds data outside the object machinery.  This47// is necessary to pass safely between interpreters in the same process.48struct _xidata {49    // data is the cross-interpreter-safe derivation of a Python object50    // (see _PyObject_GetXIData).  It will be NULL if the51    // new_object func (below) encodes the data.52    void *data;53    // obj is the Python object from which the data was derived.  This54    // is non-NULL only if the data remains bound to the object in some55    // way, such that the object must be "released" (via a decref) when56    // the data is released.  In that case the code that sets the field,57    // likely a registered "xidatafunc", is responsible for58    // ensuring it owns the reference (i.e. incref).59    PyObject *obj;60    // interpid is the ID of the owning interpreter of the original61    // object.  It corresponds to the active interpreter when62    // _PyObject_GetXIData() was called.  This should only63    // be set by the cross-interpreter machinery.64    //65    // We use the ID rather than the PyInterpreterState to avoid issues66    // with deleted interpreters.  Note that IDs are never re-used, so67    // each one will always correspond to a specific interpreter68    // (whether still alive or not).69    int64_t interpid;70    // new_object is a function that returns a new object in the current71    // interpreter given the data.  The resulting object (a new72    // reference) will be equivalent to the original object.  This field73    // is required.74    xid_newobjfunc new_object;75    // free is called when the data is released.  If it is NULL then76    // nothing will be done to free the data.  For some types this is77    // okay (e.g. bytes) and for those types this field should be set78    // to NULL.  However, for most the data was allocated just for79    // cross-interpreter use, so it must be freed when80    // _PyXIData_Release is called or the memory will81    // leak.  In that case, at the very least this field should be set82    // to PyMem_RawFree (the default if not explicitly set to NULL).83    // The call will happen with the original interpreter activated.84    xid_freefunc free;85};86 87PyAPI_FUNC(_PyXIData_t *) _PyXIData_New(void);88PyAPI_FUNC(void) _PyXIData_Free(_PyXIData_t *data);89 90#define _PyXIData_DATA(DATA) ((DATA)->data)91#define _PyXIData_OBJ(DATA) ((DATA)->obj)92#define _PyXIData_INTERPID(DATA) ((DATA)->interpid)93// Users should not need getters for "new_object" or "free".94 95 96/* defining cross-interpreter data */97 98PyAPI_FUNC(void) _PyXIData_Init(99        _PyXIData_t *data,100        PyInterpreterState *interp, void *shared, PyObject *obj,101        xid_newobjfunc new_object);102PyAPI_FUNC(int) _PyXIData_InitWithSize(103        _PyXIData_t *,104        PyInterpreterState *interp, const size_t, PyObject *,105        xid_newobjfunc);106PyAPI_FUNC(void) _PyXIData_Clear(PyInterpreterState *, _PyXIData_t *);107 108// Normally the Init* functions are sufficient.  The only time109// additional initialization might be needed is to set the "free" func,110// though that should be infrequent.111#define _PyXIData_SET_FREE(DATA, FUNC) \112    do { \113        (DATA)->free = (FUNC); \114    } while (0)115#define _PyXIData_CHECK_FREE(DATA, FUNC) \116    ((DATA)->free == (FUNC))117// Additionally, some shareable types are essentially light wrappers118// around other shareable types.  The xidatafunc of the wrapper119// can often be implemented by calling the wrapped object's120// xidatafunc and then changing the "new_object" function.121// We have _PyXIData_SET_NEW_OBJECT() here for that,122// but might be better to have a function like123// _PyXIData_AdaptToWrapper() instead.124#define _PyXIData_SET_NEW_OBJECT(DATA, FUNC) \125    do { \126        (DATA)->new_object = (FUNC); \127    } while (0)128#define _PyXIData_CHECK_NEW_OBJECT(DATA, FUNC) \129    ((DATA)->new_object == (FUNC))130 131 132/* getting cross-interpreter data */133 134typedef int xidata_fallback_t;135#define _PyXIDATA_XIDATA_ONLY (0)136#define _PyXIDATA_FULL_FALLBACK (1)137 138// Technically, we don't need two different function types;139// we could go with just the fallback one.  However, only container140// types like tuple need it, so always having the extra arg would be141// a bit unfortunate.  It's also nice to be able to clearly distinguish142// between types that might call _PyObject_GetXIData() and those that won't.143//144typedef int (*xidatafunc)(PyThreadState *, PyObject *, _PyXIData_t *);145typedef int (*xidatafbfunc)(146        PyThreadState *, PyObject *, xidata_fallback_t, _PyXIData_t *);147typedef struct {148    xidatafunc basic;149    xidatafbfunc fallback;150} _PyXIData_getdata_t;151 152PyAPI_FUNC(PyObject *) _PyXIData_GetNotShareableErrorType(PyThreadState *);153PyAPI_FUNC(void) _PyXIData_SetNotShareableError(PyThreadState *, const char *);154PyAPI_FUNC(void) _PyXIData_FormatNotShareableError(155        PyThreadState *,156        const char *,157        ...);158 159PyAPI_FUNC(_PyXIData_getdata_t) _PyXIData_Lookup(160        PyThreadState *,161        PyObject *);162PyAPI_FUNC(int) _PyObject_CheckXIData(163        PyThreadState *,164        PyObject *);165 166PyAPI_FUNC(int) _PyObject_GetXIDataNoFallback(167        PyThreadState *,168        PyObject *,169        _PyXIData_t *);170PyAPI_FUNC(int) _PyObject_GetXIData(171        PyThreadState *,172        PyObject *,173        xidata_fallback_t,174        _PyXIData_t *);175 176// _PyObject_GetXIData() for bytes177typedef struct {178    const char *bytes;179    Py_ssize_t len;180} _PyBytes_data_t;181PyAPI_FUNC(int) _PyBytes_GetData(PyObject *, _PyBytes_data_t *);182PyAPI_FUNC(PyObject *) _PyBytes_FromData(_PyBytes_data_t *);183PyAPI_FUNC(PyObject *) _PyBytes_FromXIData(_PyXIData_t *);184PyAPI_FUNC(int) _PyBytes_GetXIData(185        PyThreadState *,186        PyObject *,187        _PyXIData_t *);188PyAPI_FUNC(_PyBytes_data_t *) _PyBytes_GetXIDataWrapped(189        PyThreadState *,190        PyObject *,191        size_t,192        xid_newobjfunc,193        _PyXIData_t *);194 195// _PyObject_GetXIData() for pickle196PyAPI_DATA(PyObject *) _PyPickle_LoadFromXIData(_PyXIData_t *);197PyAPI_FUNC(int) _PyPickle_GetXIData(198        PyThreadState *,199        PyObject *,200        _PyXIData_t *);201 202// _PyObject_GetXIData() for marshal203PyAPI_FUNC(PyObject *) _PyMarshal_ReadObjectFromXIData(_PyXIData_t *);204PyAPI_FUNC(int) _PyMarshal_GetXIData(205        PyThreadState *,206        PyObject *,207        _PyXIData_t *);208 209// _PyObject_GetXIData() for code objects210PyAPI_FUNC(PyObject *) _PyCode_FromXIData(_PyXIData_t *);211PyAPI_FUNC(int) _PyCode_GetXIData(212        PyThreadState *,213        PyObject *,214        _PyXIData_t *);215PyAPI_FUNC(int) _PyCode_GetScriptXIData(216        PyThreadState *,217        PyObject *,218        _PyXIData_t *);219PyAPI_FUNC(int) _PyCode_GetPureScriptXIData(220        PyThreadState *,221        PyObject *,222        _PyXIData_t *);223 224// _PyObject_GetXIData() for functions225PyAPI_FUNC(PyObject *) _PyFunction_FromXIData(_PyXIData_t *);226PyAPI_FUNC(int) _PyFunction_GetXIData(227        PyThreadState *,228        PyObject *,229        _PyXIData_t *);230 231 232/* using cross-interpreter data */233 234PyAPI_FUNC(PyObject *) _PyXIData_NewObject(_PyXIData_t *);235PyAPI_FUNC(int) _PyXIData_Release(_PyXIData_t *);236PyAPI_FUNC(int) _PyXIData_ReleaseAndRawFree(_PyXIData_t *);237 238 239/* cross-interpreter data registry */240 241#define Py_CORE_CROSSINTERP_DATA_REGISTRY_H242#include "pycore_crossinterp_data_registry.h"243#undef Py_CORE_CROSSINTERP_DATA_REGISTRY_H244 245 246/*****************************/247/* runtime state & lifecycle */248/*****************************/249 250typedef struct _xid_lookup_state _PyXIData_lookup_t;251 252typedef struct {253    // builtin types254    _PyXIData_lookup_t data_lookup;255} _PyXI_global_state_t;256 257typedef struct {258    // heap types259    _PyXIData_lookup_t data_lookup;260 261    struct xi_exceptions {262        // static types263        PyObject *PyExc_InterpreterError;264        PyObject *PyExc_InterpreterNotFoundError;265        // heap types266        PyObject *PyExc_NotShareableError;267    } exceptions;268} _PyXI_state_t;269 270#define _PyXI_GET_GLOBAL_STATE(interp) (&(interp)->runtime->xi)271#define _PyXI_GET_STATE(interp) (&(interp)->xi)272 273#ifndef Py_BUILD_CORE_MODULE274extern PyStatus _PyXI_Init(PyInterpreterState *interp);275extern void _PyXI_Fini(PyInterpreterState *interp);276extern PyStatus _PyXI_InitTypes(PyInterpreterState *interp);277extern void _PyXI_FiniTypes(PyInterpreterState *interp);278#endif  // Py_BUILD_CORE_MODULE279 280int _Py_xi_global_state_init(_PyXI_global_state_t *);281void _Py_xi_global_state_fini(_PyXI_global_state_t *);282int _Py_xi_state_init(_PyXI_state_t *, PyInterpreterState *);283void _Py_xi_state_fini(_PyXI_state_t *, PyInterpreterState *);284 285 286/***************************/287/* short-term data sharing */288/***************************/289 290// Ultimately we'd like to preserve enough information about the291// exception and traceback that we could re-constitute (or at least292// simulate, a la traceback.TracebackException), and even chain, a copy293// of the exception in the calling interpreter.294 295typedef struct _excinfo {296    struct _excinfo_type {297        PyTypeObject *builtin;298        const char *name;299        const char *qualname;300        const char *module;301    } type;302    const char *msg;303    const char *errdisplay;304} _PyXI_excinfo;305 306PyAPI_FUNC(_PyXI_excinfo *) _PyXI_NewExcInfo(PyObject *exc);307PyAPI_FUNC(void) _PyXI_FreeExcInfo(_PyXI_excinfo *info);308PyAPI_FUNC(PyObject *) _PyXI_FormatExcInfo(_PyXI_excinfo *info);309PyAPI_FUNC(PyObject *) _PyXI_ExcInfoAsObject(_PyXI_excinfo *info);310 311 312typedef enum error_code {313    _PyXI_ERR_NO_ERROR = 0,314    _PyXI_ERR_UNCAUGHT_EXCEPTION = -1,315    _PyXI_ERR_OTHER = -2,316    _PyXI_ERR_NO_MEMORY = -3,317    _PyXI_ERR_ALREADY_RUNNING = -4,318    _PyXI_ERR_MAIN_NS_FAILURE = -5,319    _PyXI_ERR_APPLY_NS_FAILURE = -6,320    _PyXI_ERR_PRESERVE_FAILURE = -7,321    _PyXI_ERR_EXC_PROPAGATION_FAILURE = -8,322    _PyXI_ERR_NOT_SHAREABLE = -9,323} _PyXI_errcode;324 325typedef struct xi_failure _PyXI_failure;326 327PyAPI_FUNC(_PyXI_failure *) _PyXI_NewFailure(void);328PyAPI_FUNC(void) _PyXI_FreeFailure(_PyXI_failure *);329PyAPI_FUNC(_PyXI_errcode) _PyXI_GetFailureCode(_PyXI_failure *);330PyAPI_FUNC(int) _PyXI_InitFailure(_PyXI_failure *, _PyXI_errcode, PyObject *);331PyAPI_FUNC(void) _PyXI_InitFailureUTF8(332    _PyXI_failure *,333    _PyXI_errcode,334    const char *);335 336PyAPI_FUNC(int) _PyXI_UnwrapNotShareableError(337    PyThreadState *,338    _PyXI_failure *);339 340 341// A cross-interpreter session involves entering an interpreter342// with _PyXI_Enter(), doing some work with it, and finally exiting343// that interpreter with _PyXI_Exit().344//345// At the boundaries of the session, both entering and exiting,346// data may be exchanged between the previous interpreter and the347// target one in a thread-safe way that does not violate the348// isolation between interpreters.  This includes setting objects349// in the target's __main__ module on the way in, and capturing350// uncaught exceptions on the way out.351typedef struct xi_session _PyXI_session;352 353PyAPI_FUNC(_PyXI_session *) _PyXI_NewSession(void);354PyAPI_FUNC(void) _PyXI_FreeSession(_PyXI_session *);355 356typedef struct {357    PyObject *preserved;358    PyObject *excinfo;359    _PyXI_errcode errcode;360} _PyXI_session_result;361PyAPI_FUNC(void) _PyXI_ClearResult(_PyXI_session_result *);362 363PyAPI_FUNC(int) _PyXI_Enter(364    _PyXI_session *session,365    PyInterpreterState *interp,366    PyObject *nsupdates,367    _PyXI_session_result *);368PyAPI_FUNC(int) _PyXI_Exit(369    _PyXI_session *,370    _PyXI_failure *,371    _PyXI_session_result *);372 373PyAPI_FUNC(PyObject *) _PyXI_GetMainNamespace(374    _PyXI_session *,375    _PyXI_failure *);376 377PyAPI_FUNC(int) _PyXI_Preserve(378    _PyXI_session *,379    const char *,380    PyObject *,381    _PyXI_failure *);382PyAPI_FUNC(PyObject *) _PyXI_GetPreserved(383    _PyXI_session_result *,384    const char *);385 386 387/*************/388/* other API */389/*************/390 391// Export for _testinternalcapi shared extension392PyAPI_FUNC(PyInterpreterState *) _PyXI_NewInterpreter(393    PyInterpreterConfig *config,394    long *maybe_whence,395    PyThreadState **p_tstate,396    PyThreadState **p_save_tstate);397PyAPI_FUNC(void) _PyXI_EndInterpreter(398    PyInterpreterState *interp,399    PyThreadState *tstate,400    PyThreadState **p_save_tstate);401 402 403#ifdef __cplusplus404}405#endif406#endif /* !Py_INTERNAL_CROSSINTERP_H */407 
codekingpro/portable-devtools · Team Ai