diff options
author | Victor Stinner <vstinner@python.org> | 2020-04-28 14:32:48 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-28 14:32:48 (GMT) |
commit | 7c59d7c9860cdbaf4a9c26c9142aebd3259d046e (patch) | |
tree | 25d14f4febac1b124878b5875a936b47c6706771 | |
parent | 5da352616fb8290e3c2c0245f553280824093c6a (diff) | |
download | cpython-7c59d7c9860cdbaf4a9c26c9142aebd3259d046e.zip cpython-7c59d7c9860cdbaf4a9c26c9142aebd3259d046e.tar.gz cpython-7c59d7c9860cdbaf4a9c26c9142aebd3259d046e.tar.bz2 |
bpo-40421: Add pyframe.h header file (GH-19755)
Add a new separated pyframe.h header file of the PyFrame public C
API: it is included by Python.h.
Add PyFrame_GetLineNumber() to the limited C API.
Replace "struct _frame" with "PyFrameObject" in header files.
PyFrameObject is now defined as struct _frame by pyframe.h which is
included early enough in Python.h.
-rw-r--r-- | Doc/c-api/reflection.rst | 2 | ||||
-rw-r--r-- | Doc/whatsnew/3.9.rst | 3 | ||||
-rw-r--r-- | Include/Python.h | 1 | ||||
-rw-r--r-- | Include/ceval.h | 8 | ||||
-rw-r--r-- | Include/cpython/ceval.h | 2 | ||||
-rw-r--r-- | Include/cpython/frameobject.h | 7 | ||||
-rw-r--r-- | Include/cpython/pystate.h | 6 | ||||
-rw-r--r-- | Include/cpython/traceback.h | 2 | ||||
-rw-r--r-- | Include/frameobject.h | 4 | ||||
-rw-r--r-- | Include/genobject.h | 12 | ||||
-rw-r--r-- | Include/internal/pycore_ceval.h | 3 | ||||
-rw-r--r-- | Include/internal/pycore_traceback.h | 2 | ||||
-rw-r--r-- | Include/pyframe.h | 20 | ||||
-rw-r--r-- | Include/pystate.h | 3 | ||||
-rw-r--r-- | Include/traceback.h | 4 | ||||
-rw-r--r-- | Makefile.pre.in | 1 | ||||
-rw-r--r-- | Objects/frameobject.c | 7 | ||||
-rw-r--r-- | PCbuild/pythoncore.vcxproj | 15 | ||||
-rw-r--r-- | PCbuild/pythoncore.vcxproj.filters | 3 |
19 files changed, 63 insertions, 42 deletions
diff --git a/Doc/c-api/reflection.rst b/Doc/c-api/reflection.rst index 4d3d25e..498219f 100644 --- a/Doc/c-api/reflection.rst +++ b/Doc/c-api/reflection.rst @@ -35,6 +35,8 @@ Reflection Return the line number that *frame* is currently executing. + *frame* must not be ``NULL``. + .. c:function:: const char* PyEval_GetFuncName(PyObject *func) diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index 13cd09b..8b8aa9a 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -537,6 +537,9 @@ Optimizations Build and C API Changes ======================= +* Add :c:func:`PyFrame_GetLineNumber` to the limited C API. + (Contributed by Victor Stinner in :issue:`40421`.) + * New :c:func:`PyThreadState_GetInterpreter` and :c:func:`PyInterpreterState_Get` functions to get the interpreter. New :c:func:`PyThreadState_GetFrame` function to get the current frame of a diff --git a/Include/Python.h b/Include/Python.h index 7fdb9df..868e31b 100644 --- a/Include/Python.h +++ b/Include/Python.h @@ -114,6 +114,7 @@ #include "classobject.h" #include "fileobject.h" #include "pycapsule.h" +#include "pyframe.h" #include "traceback.h" #include "sliceobject.h" #include "cellobject.h" diff --git a/Include/ceval.h b/Include/ceval.h index a70c421..df52539 100644 --- a/Include/ceval.h +++ b/Include/ceval.h @@ -28,12 +28,10 @@ Py_DEPRECATED(3.9) PyAPI_FUNC(PyObject *) PyEval_CallFunction( Py_DEPRECATED(3.9) PyAPI_FUNC(PyObject *) PyEval_CallMethod( PyObject *obj, const char *name, const char *format, ...); -struct _frame; /* Avoid including frameobject.h */ - PyAPI_FUNC(PyObject *) PyEval_GetBuiltins(void); PyAPI_FUNC(PyObject *) PyEval_GetGlobals(void); PyAPI_FUNC(PyObject *) PyEval_GetLocals(void); -PyAPI_FUNC(struct _frame *) PyEval_GetFrame(void); +PyAPI_FUNC(PyFrameObject *) PyEval_GetFrame(void); PyAPI_FUNC(int) Py_AddPendingCall(int (*func)(void *), void *arg); PyAPI_FUNC(int) Py_MakePendingCalls(void); @@ -80,8 +78,8 @@ PyAPI_FUNC(void) Py_LeaveRecursiveCall(void); PyAPI_FUNC(const char *) PyEval_GetFuncName(PyObject *); PyAPI_FUNC(const char *) PyEval_GetFuncDesc(PyObject *); -PyAPI_FUNC(PyObject *) PyEval_EvalFrame(struct _frame *); -PyAPI_FUNC(PyObject *) PyEval_EvalFrameEx(struct _frame *f, int exc); +PyAPI_FUNC(PyObject *) PyEval_EvalFrame(PyFrameObject *); +PyAPI_FUNC(PyObject *) PyEval_EvalFrameEx(PyFrameObject *f, int exc); /* Interface for threads. diff --git a/Include/cpython/ceval.h b/Include/cpython/ceval.h index 020f787..e1922a6 100644 --- a/Include/cpython/ceval.h +++ b/Include/cpython/ceval.h @@ -23,7 +23,7 @@ PyAPI_FUNC(PyObject *) _PyEval_GetBuiltinId(_Py_Identifier *); flag was set, else return 0. */ PyAPI_FUNC(int) PyEval_MergeCompilerFlags(PyCompilerFlags *cf); -PyAPI_FUNC(PyObject *) _PyEval_EvalFrameDefault(PyThreadState *tstate, struct _frame *f, int exc); +PyAPI_FUNC(PyObject *) _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int exc); PyAPI_FUNC(void) _PyEval_SetSwitchInterval(unsigned long microseconds); PyAPI_FUNC(unsigned long) _PyEval_GetSwitchInterval(void); diff --git a/Include/cpython/frameobject.h b/Include/cpython/frameobject.h index 4ced967..e819cef 100644 --- a/Include/cpython/frameobject.h +++ b/Include/cpython/frameobject.h @@ -14,7 +14,7 @@ typedef struct { int b_level; /* value stack level to pop to */ } PyTryBlock; -typedef struct _frame { +struct _frame { PyObject_VAR_HEAD struct _frame *f_back; /* previous frame, or NULL */ PyCodeObject *f_code; /* code segment */ @@ -44,7 +44,7 @@ typedef struct _frame { char f_executing; /* whether the frame is still executing */ PyTryBlock f_blockstack[CO_MAXBLOCKS]; /* for try and loop blocks */ PyObject *f_localsplus[1]; /* locals+stack, dynamically sized */ -} PyFrameObject; +}; /* Standard object interface */ @@ -79,9 +79,6 @@ PyAPI_FUNC(int) PyFrame_ClearFreeList(void); PyAPI_FUNC(void) _PyFrame_DebugMallocStats(FILE *out); -/* Return the line of code the frame is currently executing. */ -PyAPI_FUNC(int) PyFrame_GetLineNumber(PyFrameObject *); - #ifdef __cplusplus } #endif diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index 9b28f66..f292da1 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -16,7 +16,7 @@ PyAPI_FUNC(PyObject *) _PyInterpreterState_GetMainModule(PyInterpreterState *); /* State unique per thread */ /* Py_tracefunc return -1 when raising an exception, or 0 for success. */ -typedef int (*Py_tracefunc)(PyObject *, struct _frame *, int, PyObject *); +typedef int (*Py_tracefunc)(PyObject *, PyFrameObject *, int, PyObject *); /* The following values are used for 'what' for tracefunc functions * @@ -56,7 +56,7 @@ struct _ts { PyInterpreterState *interp; /* Borrowed reference to the current frame (it can be NULL) */ - struct _frame *frame; + PyFrameObject *frame; int recursion_depth; char overflowed; /* The stack has overflowed. Allow 50 more calls to handle the runtime error. */ @@ -184,7 +184,7 @@ PyAPI_FUNC(void) PyThreadState_DeleteCurrent(void); /* Frame evaluation API */ -typedef PyObject* (*_PyFrameEvalFunction)(PyThreadState *tstate, struct _frame *, int); +typedef PyObject* (*_PyFrameEvalFunction)(PyThreadState *tstate, PyFrameObject *, int); PyAPI_FUNC(_PyFrameEvalFunction) _PyInterpreterState_GetEvalFrameFunc( PyInterpreterState *interp); diff --git a/Include/cpython/traceback.h b/Include/cpython/traceback.h index 746097d..837470c 100644 --- a/Include/cpython/traceback.h +++ b/Include/cpython/traceback.h @@ -9,7 +9,7 @@ extern "C" { typedef struct _traceback { PyObject_HEAD struct _traceback *tb_next; - struct _frame *tb_frame; + PyFrameObject *tb_frame; int tb_lasti; int tb_lineno; } PyTracebackObject; diff --git a/Include/frameobject.h b/Include/frameobject.h index 1460e22..c118af1 100644 --- a/Include/frameobject.h +++ b/Include/frameobject.h @@ -6,9 +6,7 @@ extern "C" { #endif -/* There are currently no frame related APIs in the stable ABI - * (they're all in the full CPython-specific API) - */ +#include "pyframe.h" #ifndef Py_LIMITED_API # define Py_CPYTHON_FRAMEOBJECT_H diff --git a/Include/genobject.h b/Include/genobject.h index b87a648..a7393a9 100644 --- a/Include/genobject.h +++ b/Include/genobject.h @@ -10,14 +10,12 @@ extern "C" { #include "pystate.h" /* _PyErr_StackItem */ -struct _frame; /* Avoid including frameobject.h */ - /* _PyGenObject_HEAD defines the initial segment of generator and coroutine objects. */ #define _PyGenObject_HEAD(prefix) \ PyObject_HEAD \ /* Note: gi_frame can be NULL if the generator is "finished" */ \ - struct _frame *prefix##_frame; \ + PyFrameObject *prefix##_frame; \ /* True if generator is being executed. */ \ char prefix##_running; \ /* The code object backing the generator */ \ @@ -40,8 +38,8 @@ PyAPI_DATA(PyTypeObject) PyGen_Type; #define PyGen_Check(op) PyObject_TypeCheck(op, &PyGen_Type) #define PyGen_CheckExact(op) Py_IS_TYPE(op, &PyGen_Type) -PyAPI_FUNC(PyObject *) PyGen_New(struct _frame *); -PyAPI_FUNC(PyObject *) PyGen_NewWithQualName(struct _frame *, +PyAPI_FUNC(PyObject *) PyGen_New(PyFrameObject *); +PyAPI_FUNC(PyObject *) PyGen_NewWithQualName(PyFrameObject *, PyObject *name, PyObject *qualname); PyAPI_FUNC(int) _PyGen_SetStopIterationValue(PyObject *); PyAPI_FUNC(int) _PyGen_FetchStopIterationValue(PyObject **); @@ -60,7 +58,7 @@ PyAPI_DATA(PyTypeObject) _PyCoroWrapper_Type; #define PyCoro_CheckExact(op) Py_IS_TYPE(op, &PyCoro_Type) PyObject *_PyCoro_GetAwaitableIter(PyObject *o); -PyAPI_FUNC(PyObject *) PyCoro_New(struct _frame *, +PyAPI_FUNC(PyObject *) PyCoro_New(PyFrameObject *, PyObject *name, PyObject *qualname); /* Asynchronous Generators */ @@ -86,7 +84,7 @@ PyAPI_DATA(PyTypeObject) _PyAsyncGenASend_Type; PyAPI_DATA(PyTypeObject) _PyAsyncGenWrappedValue_Type; PyAPI_DATA(PyTypeObject) _PyAsyncGenAThrow_Type; -PyAPI_FUNC(PyObject *) PyAsyncGen_New(struct _frame *, +PyAPI_FUNC(PyObject *) PyAsyncGen_New(PyFrameObject *, PyObject *name, PyObject *qualname); #define PyAsyncGen_CheckExact(op) Py_IS_TYPE(op, &PyAsyncGen_Type) diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index 050dd59..2df796d 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -11,7 +11,6 @@ extern "C" { /* Forward declarations */ struct pyruntimestate; struct _ceval_runtime_state; -struct _frame; #include "pycore_interp.h" /* PyInterpreterState.eval_frame */ @@ -36,7 +35,7 @@ PyAPI_FUNC(void) _PyEval_SetCoroutineOriginTrackingDepth( void _PyEval_Fini(void); static inline PyObject* -_PyEval_EvalFrame(PyThreadState *tstate, struct _frame *f, int throwflag) +_PyEval_EvalFrame(PyThreadState *tstate, PyFrameObject *f, int throwflag) { return tstate->interp->eval_frame(tstate, f, throwflag); } diff --git a/Include/internal/pycore_traceback.h b/Include/internal/pycore_traceback.h index 99443d7..1f09241 100644 --- a/Include/internal/pycore_traceback.h +++ b/Include/internal/pycore_traceback.h @@ -89,7 +89,7 @@ PyAPI_FUNC(void) _Py_DumpHexadecimal( PyAPI_FUNC(PyObject*) _PyTraceBack_FromFrame( PyObject *tb_next, - struct _frame *frame); + PyFrameObject *frame); #ifdef __cplusplus } diff --git a/Include/pyframe.h b/Include/pyframe.h new file mode 100644 index 0000000..d3404cd --- /dev/null +++ b/Include/pyframe.h @@ -0,0 +1,20 @@ +/* Limited C API of PyFrame API + * + * Include "frameobject.h" to get the PyFrameObject structure. + */ + +#ifndef Py_PYFRAME_H +#define Py_PYFRAME_H +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _frame PyFrameObject; + +/* Return the line of code the frame is currently executing. */ +PyAPI_FUNC(int) PyFrame_GetLineNumber(PyFrameObject *); + +#ifdef __cplusplus +} +#endif +#endif /* !Py_PYFRAME_H */ diff --git a/Include/pystate.h b/Include/pystate.h index 65b0a24..34cad02 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -13,7 +13,6 @@ removed (with effort). */ /* Forward declarations for PyFrameObject, PyThreadState and PyInterpreterState */ -struct _frame; struct _ts; struct _is; @@ -88,7 +87,7 @@ PyAPI_FUNC(int) PyThreadState_SetAsyncExc(unsigned long, PyObject *); #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03090000 /* New in 3.9 */ PyAPI_FUNC(PyInterpreterState*) PyThreadState_GetInterpreter(PyThreadState *tstate); -PyAPI_FUNC(struct _frame*) PyThreadState_GetFrame(PyThreadState *tstate); +PyAPI_FUNC(PyFrameObject*) PyThreadState_GetFrame(PyThreadState *tstate); PyAPI_FUNC(uint64_t) PyThreadState_GetID(PyThreadState *tstate); #endif diff --git a/Include/traceback.h b/Include/traceback.h index 0efbae8..781e5a6 100644 --- a/Include/traceback.h +++ b/Include/traceback.h @@ -4,11 +4,9 @@ extern "C" { #endif -struct _frame; - /* Traceback interface */ -PyAPI_FUNC(int) PyTraceBack_Here(struct _frame *); +PyAPI_FUNC(int) PyTraceBack_Here(PyFrameObject *); PyAPI_FUNC(int) PyTraceBack_Print(PyObject *, PyObject *); /* Reveal traceback type so we can typecheck traceback objects */ diff --git a/Makefile.pre.in b/Makefile.pre.in index 200fd31..5db381f 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1047,6 +1047,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/pydtrace.h \ $(srcdir)/Include/pyerrors.h \ $(srcdir)/Include/pyfpe.h \ + $(srcdir)/Include/pyframe.h \ $(srcdir)/Include/pyhash.h \ $(srcdir)/Include/pylifecycle.h \ $(srcdir)/Include/pymacconfig.h \ diff --git a/Objects/frameobject.c b/Objects/frameobject.c index bdd7862..d0a15e7 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -34,10 +34,13 @@ frame_getlocals(PyFrameObject *f, void *closure) int PyFrame_GetLineNumber(PyFrameObject *f) { - if (f->f_trace) + assert(f != NULL); + if (f->f_trace) { return f->f_lineno; - else + } + else { return PyCode_Addr2Line(f->f_code, f->f_lasti); + } } static PyObject * diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index d20e749..f54f155 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -110,6 +110,8 @@ </Link> </ItemDefinitionGroup> <ItemGroup> + <ClInclude Include="..\Include\Python-ast.h" /> + <ClInclude Include="..\Include\Python.h" /> <ClInclude Include="..\Include\abstract.h" /> <ClInclude Include="..\Include\asdl.h" /> <ClInclude Include="..\Include\ast.h" /> @@ -165,8 +167,8 @@ <ClInclude Include="..\Include\internal\pycore_abstract.h" /> <ClInclude Include="..\Include\internal\pycore_accu.h" /> <ClInclude Include="..\Include\internal\pycore_atomic.h" /> - <ClInclude Include="..\Include\internal\pycore_byteswap.h" /> <ClInclude Include="..\Include\internal\pycore_bytes_methods.h" /> + <ClInclude Include="..\Include\internal\pycore_byteswap.h" /> <ClInclude Include="..\Include\internal\pycore_call.h" /> <ClInclude Include="..\Include\internal\pycore_ceval.h" /> <ClInclude Include="..\Include\internal\pycore_code.h" /> @@ -214,7 +216,6 @@ <ClInclude Include="..\Include\parsetok.h" /> <ClInclude Include="..\Include\patchlevel.h" /> <ClInclude Include="..\Include\picklebufobject.h" /> - <ClInclude Include="..\Include\pyhash.h" /> <ClInclude Include="..\Include\py_curses.h" /> <ClInclude Include="..\Include\pyarena.h" /> <ClInclude Include="..\Include\pycapsule.h" /> @@ -223,20 +224,20 @@ <ClInclude Include="..\Include\pyerrors.h" /> <ClInclude Include="..\Include\pyexpat.h" /> <ClInclude Include="..\Include\pyfpe.h" /> + <ClInclude Include="..\Include\pyframe.h" /> + <ClInclude Include="..\Include\pyhash.h" /> <ClInclude Include="..\Include\pylifecycle.h" /> - <ClInclude Include="..\Include\pymath.h" /> - <ClInclude Include="..\Include\pytime.h" /> <ClInclude Include="..\Include\pymacro.h" /> + <ClInclude Include="..\Include\pymath.h" /> <ClInclude Include="..\Include\pymem.h" /> <ClInclude Include="..\Include\pyport.h" /> <ClInclude Include="..\Include\pystate.h" /> <ClInclude Include="..\Include\pystrcmp.h" /> - <ClInclude Include="..\Include\pystrtod.h" /> <ClInclude Include="..\Include\pystrhex.h" /> - <ClInclude Include="..\Include\Python-ast.h" /> - <ClInclude Include="..\Include\Python.h" /> + <ClInclude Include="..\Include\pystrtod.h" /> <ClInclude Include="..\Include\pythonrun.h" /> <ClInclude Include="..\Include\pythread.h" /> + <ClInclude Include="..\Include\pytime.h" /> <ClInclude Include="..\Include\rangeobject.h" /> <ClInclude Include="..\Include\setobject.h" /> <ClInclude Include="..\Include\sliceobject.h" /> diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 8c02622..c8758da 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -249,6 +249,9 @@ <ClInclude Include="..\Include\internal\pycore_pyerrors.h"> <Filter>Include</Filter> </ClInclude> + <ClInclude Include="..\Include\internal\pycore_pyframe.h"> + <Filter>Include</Filter> + </ClInclude> <ClInclude Include="..\Include\internal\pycore_pyhash.h"> <Filter>Include</Filter> </ClInclude> |