python 2.7 -> python 3.14
This commit is contained in:
406
extern/include/python/internal/pycore_crossinterp.h
vendored
Normal file
406
extern/include/python/internal/pycore_crossinterp.h
vendored
Normal file
@@ -0,0 +1,406 @@
|
||||
#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
|
||||
|
||||
#include "pycore_pyerrors.h"
|
||||
|
||||
|
||||
/**************/
|
||||
/* exceptions */
|
||||
/**************/
|
||||
|
||||
PyAPI_DATA(PyObject *) PyExc_InterpreterError;
|
||||
PyAPI_DATA(PyObject *) PyExc_InterpreterNotFoundError;
|
||||
|
||||
|
||||
/***************************/
|
||||
/* 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 */
|
||||
/**************************/
|
||||
|
||||
typedef struct _xidata _PyXIData_t;
|
||||
typedef PyObject *(*xid_newobjfunc)(_PyXIData_t *);
|
||||
typedef void (*xid_freefunc)(void *);
|
||||
|
||||
// _PyXIData_t is similar to Py_buffer as an effectively
|
||||
// opaque struct that holds data outside the object machinery. This
|
||||
// is necessary to pass safely between interpreters in the same process.
|
||||
struct _xidata {
|
||||
// data is the cross-interpreter-safe derivation of a Python object
|
||||
// (see _PyObject_GetXIData). It will be NULL if the
|
||||
// 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,
|
||||
// likely a registered "xidatafunc", is responsible for
|
||||
// ensuring it owns the reference (i.e. incref).
|
||||
PyObject *obj;
|
||||
// interpid is the ID of the owning interpreter of the original
|
||||
// object. It corresponds to the active interpreter when
|
||||
// _PyObject_GetXIData() was called. This should only
|
||||
// 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.
|
||||
xid_newobjfunc new_object;
|
||||
// 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
|
||||
// _PyXIData_Release is called or the memory will
|
||||
// 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;
|
||||
};
|
||||
|
||||
PyAPI_FUNC(_PyXIData_t *) _PyXIData_New(void);
|
||||
PyAPI_FUNC(void) _PyXIData_Free(_PyXIData_t *data);
|
||||
|
||||
#define _PyXIData_DATA(DATA) ((DATA)->data)
|
||||
#define _PyXIData_OBJ(DATA) ((DATA)->obj)
|
||||
#define _PyXIData_INTERPID(DATA) ((DATA)->interpid)
|
||||
// Users should not need getters for "new_object" or "free".
|
||||
|
||||
|
||||
/* defining cross-interpreter data */
|
||||
|
||||
PyAPI_FUNC(void) _PyXIData_Init(
|
||||
_PyXIData_t *data,
|
||||
PyInterpreterState *interp, void *shared, PyObject *obj,
|
||||
xid_newobjfunc new_object);
|
||||
PyAPI_FUNC(int) _PyXIData_InitWithSize(
|
||||
_PyXIData_t *,
|
||||
PyInterpreterState *interp, const size_t, PyObject *,
|
||||
xid_newobjfunc);
|
||||
PyAPI_FUNC(void) _PyXIData_Clear(PyInterpreterState *, _PyXIData_t *);
|
||||
|
||||
// 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.
|
||||
#define _PyXIData_SET_FREE(DATA, FUNC) \
|
||||
do { \
|
||||
(DATA)->free = (FUNC); \
|
||||
} while (0)
|
||||
#define _PyXIData_CHECK_FREE(DATA, FUNC) \
|
||||
((DATA)->free == (FUNC))
|
||||
// Additionally, some shareable types are essentially light wrappers
|
||||
// around other shareable types. The xidatafunc of the wrapper
|
||||
// can often be implemented by calling the wrapped object's
|
||||
// xidatafunc and then changing the "new_object" function.
|
||||
// We have _PyXIData_SET_NEW_OBJECT() here for that,
|
||||
// but might be better to have a function like
|
||||
// _PyXIData_AdaptToWrapper() instead.
|
||||
#define _PyXIData_SET_NEW_OBJECT(DATA, FUNC) \
|
||||
do { \
|
||||
(DATA)->new_object = (FUNC); \
|
||||
} while (0)
|
||||
#define _PyXIData_CHECK_NEW_OBJECT(DATA, FUNC) \
|
||||
((DATA)->new_object == (FUNC))
|
||||
|
||||
|
||||
/* getting cross-interpreter data */
|
||||
|
||||
typedef int xidata_fallback_t;
|
||||
#define _PyXIDATA_XIDATA_ONLY (0)
|
||||
#define _PyXIDATA_FULL_FALLBACK (1)
|
||||
|
||||
// Technically, we don't need two different function types;
|
||||
// we could go with just the fallback one. However, only container
|
||||
// types like tuple need it, so always having the extra arg would be
|
||||
// a bit unfortunate. It's also nice to be able to clearly distinguish
|
||||
// between types that might call _PyObject_GetXIData() and those that won't.
|
||||
//
|
||||
typedef int (*xidatafunc)(PyThreadState *, PyObject *, _PyXIData_t *);
|
||||
typedef int (*xidatafbfunc)(
|
||||
PyThreadState *, PyObject *, xidata_fallback_t, _PyXIData_t *);
|
||||
typedef struct {
|
||||
xidatafunc basic;
|
||||
xidatafbfunc fallback;
|
||||
} _PyXIData_getdata_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(_PyXIData_getdata_t) _PyXIData_Lookup(
|
||||
PyThreadState *,
|
||||
PyObject *);
|
||||
PyAPI_FUNC(int) _PyObject_CheckXIData(
|
||||
PyThreadState *,
|
||||
PyObject *);
|
||||
|
||||
PyAPI_FUNC(int) _PyObject_GetXIDataNoFallback(
|
||||
PyThreadState *,
|
||||
PyObject *,
|
||||
_PyXIData_t *);
|
||||
PyAPI_FUNC(int) _PyObject_GetXIData(
|
||||
PyThreadState *,
|
||||
PyObject *,
|
||||
xidata_fallback_t,
|
||||
_PyXIData_t *);
|
||||
|
||||
// _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 *);
|
||||
|
||||
// _PyObject_GetXIData() for pickle
|
||||
PyAPI_DATA(PyObject *) _PyPickle_LoadFromXIData(_PyXIData_t *);
|
||||
PyAPI_FUNC(int) _PyPickle_GetXIData(
|
||||
PyThreadState *,
|
||||
PyObject *,
|
||||
_PyXIData_t *);
|
||||
|
||||
// _PyObject_GetXIData() for marshal
|
||||
PyAPI_FUNC(PyObject *) _PyMarshal_ReadObjectFromXIData(_PyXIData_t *);
|
||||
PyAPI_FUNC(int) _PyMarshal_GetXIData(
|
||||
PyThreadState *,
|
||||
PyObject *,
|
||||
_PyXIData_t *);
|
||||
|
||||
// _PyObject_GetXIData() for code objects
|
||||
PyAPI_FUNC(PyObject *) _PyCode_FromXIData(_PyXIData_t *);
|
||||
PyAPI_FUNC(int) _PyCode_GetXIData(
|
||||
PyThreadState *,
|
||||
PyObject *,
|
||||
_PyXIData_t *);
|
||||
PyAPI_FUNC(int) _PyCode_GetScriptXIData(
|
||||
PyThreadState *,
|
||||
PyObject *,
|
||||
_PyXIData_t *);
|
||||
PyAPI_FUNC(int) _PyCode_GetPureScriptXIData(
|
||||
PyThreadState *,
|
||||
PyObject *,
|
||||
_PyXIData_t *);
|
||||
|
||||
// _PyObject_GetXIData() for functions
|
||||
PyAPI_FUNC(PyObject *) _PyFunction_FromXIData(_PyXIData_t *);
|
||||
PyAPI_FUNC(int) _PyFunction_GetXIData(
|
||||
PyThreadState *,
|
||||
PyObject *,
|
||||
_PyXIData_t *);
|
||||
|
||||
|
||||
/* 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 *);
|
||||
|
||||
|
||||
/* cross-interpreter data registry */
|
||||
|
||||
#define Py_CORE_CROSSINTERP_DATA_REGISTRY_H
|
||||
#include "pycore_crossinterp_data_registry.h"
|
||||
#undef Py_CORE_CROSSINTERP_DATA_REGISTRY_H
|
||||
|
||||
|
||||
/*****************************/
|
||||
/* runtime state & lifecycle */
|
||||
/*****************************/
|
||||
|
||||
typedef struct _xid_lookup_state _PyXIData_lookup_t;
|
||||
|
||||
typedef struct {
|
||||
// builtin types
|
||||
_PyXIData_lookup_t data_lookup;
|
||||
} _PyXI_global_state_t;
|
||||
|
||||
typedef struct {
|
||||
// heap types
|
||||
_PyXIData_lookup_t data_lookup;
|
||||
|
||||
struct xi_exceptions {
|
||||
// static types
|
||||
PyObject *PyExc_InterpreterError;
|
||||
PyObject *PyExc_InterpreterNotFoundError;
|
||||
// heap types
|
||||
PyObject *PyExc_NotShareableError;
|
||||
} exceptions;
|
||||
} _PyXI_state_t;
|
||||
|
||||
#define _PyXI_GET_GLOBAL_STATE(interp) (&(interp)->runtime->xi)
|
||||
#define _PyXI_GET_STATE(interp) (&(interp)->xi)
|
||||
|
||||
#ifndef Py_BUILD_CORE_MODULE
|
||||
extern PyStatus _PyXI_Init(PyInterpreterState *interp);
|
||||
extern void _PyXI_Fini(PyInterpreterState *interp);
|
||||
extern PyStatus _PyXI_InitTypes(PyInterpreterState *interp);
|
||||
extern void _PyXI_FiniTypes(PyInterpreterState *interp);
|
||||
#endif // Py_BUILD_CORE_MODULE
|
||||
|
||||
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 *);
|
||||
|
||||
|
||||
/***************************/
|
||||
/* short-term data sharing */
|
||||
/***************************/
|
||||
|
||||
// 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 {
|
||||
struct _excinfo_type {
|
||||
PyTypeObject *builtin;
|
||||
const char *name;
|
||||
const char *qualname;
|
||||
const char *module;
|
||||
} type;
|
||||
const char *msg;
|
||||
const char *errdisplay;
|
||||
} _PyXI_excinfo;
|
||||
|
||||
PyAPI_FUNC(_PyXI_excinfo *) _PyXI_NewExcInfo(PyObject *exc);
|
||||
PyAPI_FUNC(void) _PyXI_FreeExcInfo(_PyXI_excinfo *info);
|
||||
PyAPI_FUNC(PyObject *) _PyXI_FormatExcInfo(_PyXI_excinfo *info);
|
||||
PyAPI_FUNC(PyObject *) _PyXI_ExcInfoAsObject(_PyXI_excinfo *info);
|
||||
|
||||
|
||||
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_PRESERVE_FAILURE = -7,
|
||||
_PyXI_ERR_EXC_PROPAGATION_FAILURE = -8,
|
||||
_PyXI_ERR_NOT_SHAREABLE = -9,
|
||||
} _PyXI_errcode;
|
||||
|
||||
typedef struct xi_failure _PyXI_failure;
|
||||
|
||||
PyAPI_FUNC(_PyXI_failure *) _PyXI_NewFailure(void);
|
||||
PyAPI_FUNC(void) _PyXI_FreeFailure(_PyXI_failure *);
|
||||
PyAPI_FUNC(_PyXI_errcode) _PyXI_GetFailureCode(_PyXI_failure *);
|
||||
PyAPI_FUNC(int) _PyXI_InitFailure(_PyXI_failure *, _PyXI_errcode, PyObject *);
|
||||
PyAPI_FUNC(void) _PyXI_InitFailureUTF8(
|
||||
_PyXI_failure *,
|
||||
_PyXI_errcode,
|
||||
const char *);
|
||||
|
||||
PyAPI_FUNC(int) _PyXI_UnwrapNotShareableError(
|
||||
PyThreadState *,
|
||||
_PyXI_failure *);
|
||||
|
||||
|
||||
// A cross-interpreter session involves entering an interpreter
|
||||
// with _PyXI_Enter(), doing some work with it, and finally exiting
|
||||
// that interpreter with _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.
|
||||
typedef struct xi_session _PyXI_session;
|
||||
|
||||
PyAPI_FUNC(_PyXI_session *) _PyXI_NewSession(void);
|
||||
PyAPI_FUNC(void) _PyXI_FreeSession(_PyXI_session *);
|
||||
|
||||
typedef struct {
|
||||
PyObject *preserved;
|
||||
PyObject *excinfo;
|
||||
_PyXI_errcode errcode;
|
||||
} _PyXI_session_result;
|
||||
PyAPI_FUNC(void) _PyXI_ClearResult(_PyXI_session_result *);
|
||||
|
||||
PyAPI_FUNC(int) _PyXI_Enter(
|
||||
_PyXI_session *session,
|
||||
PyInterpreterState *interp,
|
||||
PyObject *nsupdates,
|
||||
_PyXI_session_result *);
|
||||
PyAPI_FUNC(int) _PyXI_Exit(
|
||||
_PyXI_session *,
|
||||
_PyXI_failure *,
|
||||
_PyXI_session_result *);
|
||||
|
||||
PyAPI_FUNC(PyObject *) _PyXI_GetMainNamespace(
|
||||
_PyXI_session *,
|
||||
_PyXI_failure *);
|
||||
|
||||
PyAPI_FUNC(int) _PyXI_Preserve(
|
||||
_PyXI_session *,
|
||||
const char *,
|
||||
PyObject *,
|
||||
_PyXI_failure *);
|
||||
PyAPI_FUNC(PyObject *) _PyXI_GetPreserved(
|
||||
_PyXI_session_result *,
|
||||
const char *);
|
||||
|
||||
|
||||
/*************/
|
||||
/* other API */
|
||||
/*************/
|
||||
|
||||
// Export for _testinternalcapi shared extension
|
||||
PyAPI_FUNC(PyInterpreterState *) _PyXI_NewInterpreter(
|
||||
PyInterpreterConfig *config,
|
||||
long *maybe_whence,
|
||||
PyThreadState **p_tstate,
|
||||
PyThreadState **p_save_tstate);
|
||||
PyAPI_FUNC(void) _PyXI_EndInterpreter(
|
||||
PyInterpreterState *interp,
|
||||
PyThreadState *tstate,
|
||||
PyThreadState **p_save_tstate);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_CROSSINTERP_H */
|
||||
Reference in New Issue
Block a user