1 // Python Tools for Visual Studio 2 // Copyright(c) Microsoft Corporation 3 // All rights reserved. 4 // 5 // Licensed under the Apache License, Version 2.0 (the License); you may not use 6 // this file except in compliance with the License. You may obtain a copy of the 7 // License at http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS 10 // OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY 11 // IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 12 // MERCHANTABILITY OR NON-INFRINGEMENT. 13 // 14 // See the Apache Version 2.0 License for specific language governing 15 // permissions and limitations under the License. 16 17 #ifndef __PYTHON_H__ 18 #define __PYTHON_H__ 19 20 #include "../common/py_version.hpp" 21 22 #ifndef _WIN32 23 typedef unsigned int DWORD; 24 typedef ssize_t SSIZE_T; 25 #endif 26 typedef SSIZE_T Py_ssize_t; 27 28 // defines limited header of Python API for compatible access across a number of Pythons. 29 30 class PyTypeObject; 31 class PyThreadState; 32 33 #define PyObject_HEAD \ 34 size_t ob_refcnt; \ 35 PyTypeObject *ob_type; 36 37 #define PyObject_VAR_HEAD \ 38 PyObject_HEAD \ 39 size_t ob_size; /* Number of items in variable part */ 40 41 class PyObject { 42 public: 43 PyObject_HEAD 44 }; 45 46 class PyVarObject : public PyObject { 47 public: 48 size_t ob_size; /* Number of items in variable part */ 49 }; 50 51 // 2.5 - 3.7 52 class PyFunctionObject : public PyObject { 53 public: 54 PyObject *func_code; /* A code object */ 55 }; 56 57 // 2.5 - 2.7 compatible 58 class PyStringObject : public PyVarObject { 59 public: 60 long ob_shash; 61 int ob_sstate; 62 char ob_sval[1]; 63 64 /* Invariants: 65 * ob_sval contains space for 'ob_size+1' elements. 66 * ob_sval[ob_size] == 0. 67 * ob_shash is the hash of the string or -1 if not computed yet. 68 * ob_sstate != 0 iff the string object is in stringobject.c's 69 * 'interned' dictionary; in this case the two references 70 * from 'interned' to this object are *not counted* in ob_refcnt. 71 */ 72 }; 73 74 // 2.4 - 3.7 compatible 75 typedef struct { 76 PyObject_HEAD 77 size_t length; /* Length of raw Unicode data in buffer */ 78 wchar_t *str; /* Raw Unicode buffer */ 79 long hash; /* Hash value; -1 if not set */ 80 } PyUnicodeObject; 81 82 83 class PyFrameObject : public PyVarObject { 84 // After 3.10 we don't really have things we want to reuse common, so, 85 // create an empty base (based on PyVarObject). 86 }; 87 88 // 2.4 - 3.7 compatible 89 class PyFrameObjectBaseUpTo39 : public PyFrameObject { 90 public: 91 PyFrameObjectBaseUpTo39 *f_back; /* previous frame, or nullptr */ 92 PyObject *f_code; /* code segment */ 93 PyObject *f_builtins; /* builtin symbol table (PyDictObject) */ 94 PyObject *f_globals; /* global symbol table (PyDictObject) */ 95 PyObject *f_locals; /* local symbol table (any mapping) */ 96 PyObject **f_valuestack; /* points after the last local */ 97 /* Next free slot in f_valuestack. Frame creation sets to f_valuestack. 98 Frame evaluation usually NULLs it, but a frame that yields sets it 99 to the current stack top. */ 100 PyObject **f_stacktop; 101 PyObject *f_trace; /* Trace function */ 102 103 // It has more things, but we're only interested in things up to f_trace. 104 105 }; 106 107 108 // https://github.com/python/cpython/blob/3.10/Include/cpython/frameobject.h 109 class PyFrameObject310 : public PyFrameObject { 110 public: 111 PyFrameObject310 *f_back; /* previous frame, or NULL */ 112 PyObject *f_code; /* code segment */ 113 PyObject *f_builtins; /* builtin symbol table (PyDictObject) */ 114 PyObject *f_globals; /* global symbol table (PyDictObject) */ 115 PyObject *f_locals; /* local symbol table (any mapping) */ 116 PyObject **f_valuestack; /* points after the last local */ 117 PyObject *f_trace; /* Trace function */ 118 119 // It has more things, but we're only interested in things up to f_trace. 120 }; 121 122 123 typedef void (*destructor)(PyObject *); 124 125 // 2.4 - 3.7 126 class PyMethodDef { 127 public: 128 char *ml_name; /* The name of the built-in function/method */ 129 }; 130 131 132 // 133 // 2.5 - 3.7 134 // While these are compatible there are fields only available on later versions. 135 class PyTypeObject : public PyVarObject { 136 public: 137 const char *tp_name; /* For printing, in format "<module>.<name>" */ 138 size_t tp_basicsize, tp_itemsize; /* For allocation */ 139 140 /* Methods to implement standard operations */ 141 142 destructor tp_dealloc; 143 void *tp_print; 144 void *tp_getattr; 145 void *tp_setattr; 146 union { 147 void *tp_compare; /* 2.4 - 3.4 */ 148 void *tp_as_async; /* 3.5 - 3.7 */ 149 }; 150 void *tp_repr; 151 152 /* Method suites for standard classes */ 153 154 void *tp_as_number; 155 void *tp_as_sequence; 156 void *tp_as_mapping; 157 158 /* More standard operations (here for binary compatibility) */ 159 160 void *tp_hash; 161 void *tp_call; 162 void *tp_str; 163 void *tp_getattro; 164 void *tp_setattro; 165 166 /* Functions to access object as input/output buffer */ 167 void *tp_as_buffer; 168 169 /* Flags to define presence of optional/expanded features */ 170 long tp_flags; 171 172 const char *tp_doc; /* Documentation string */ 173 174 /* Assigned meaning in release 2.0 */ 175 /* call function for all accessible objects */ 176 void *tp_traverse; 177 178 /* delete references to contained objects */ 179 void *tp_clear; 180 181 /* Assigned meaning in release 2.1 */ 182 /* rich comparisons */ 183 void *tp_richcompare; 184 185 /* weak reference enabler */ 186 size_t tp_weaklistoffset; 187 188 /* Added in release 2.2 */ 189 /* Iterators */ 190 void *tp_iter; 191 void *tp_iternext; 192 193 /* Attribute descriptor and subclassing stuff */ 194 PyMethodDef *tp_methods; 195 struct PyMemberDef *tp_members; 196 struct PyGetSetDef *tp_getset; 197 struct _typeobject *tp_base; 198 PyObject *tp_dict; 199 void *tp_descr_get; 200 void *tp_descr_set; 201 size_t tp_dictoffset; 202 void *tp_init; 203 void *tp_alloc; 204 void *tp_new; 205 void *tp_free; /* Low-level free-memory routine */ 206 void *tp_is_gc; /* For PyObject_IS_GC */ 207 PyObject *tp_bases; 208 PyObject *tp_mro; /* method resolution order */ 209 PyObject *tp_cache; 210 PyObject *tp_subclasses; 211 PyObject *tp_weaklist; 212 void *tp_del; 213 214 /* Type attribute cache version tag. Added in version 2.6 */ 215 unsigned int tp_version_tag; 216 }; 217 218 // 2.4 - 3.7 219 class PyTupleObject : public PyVarObject { 220 public: 221 PyObject *ob_item[1]; 222 223 /* ob_item contains space for 'ob_size' elements. 224 * Items must normally not be nullptr, except during construction when 225 * the tuple is not yet visible outside the function that builds it. 226 */ 227 }; 228 229 // 2.4 - 3.7 230 class PyCFunctionObject : public PyObject { 231 public: 232 PyMethodDef *m_ml; /* Description of the C function to call */ 233 PyObject *m_self; /* Passed as 'self' arg to the C func, can be nullptr */ 234 PyObject *m_module; /* The __module__ attribute, can be anything */ 235 }; 236 237 typedef int (*Py_tracefunc)(PyObject *, PyFrameObject *, int, PyObject *); 238 239 #define PyTrace_CALL 0 240 #define PyTrace_EXCEPTION 1 241 #define PyTrace_LINE 2 242 #define PyTrace_RETURN 3 243 #define PyTrace_C_CALL 4 244 #define PyTrace_C_EXCEPTION 5 245 #define PyTrace_C_RETURN 6 246 247 class PyInterpreterState { 248 }; 249 250 class PyThreadState { }; 251 252 class PyThreadState_25_27 : public PyThreadState { 253 public: 254 /* See Python/ceval.c for comments explaining most fields */ 255 256 PyThreadState *next; 257 PyInterpreterState *interp; 258 259 PyFrameObjectBaseUpTo39 *frame; 260 int recursion_depth; 261 /* 'tracing' keeps track of the execution depth when tracing/profiling. 262 This is to prevent the actual trace/profile code from being recorded in 263 the trace/profile. */ 264 int tracing; 265 int use_tracing; 266 267 Py_tracefunc c_profilefunc; 268 Py_tracefunc c_tracefunc; 269 PyObject *c_profileobj; 270 PyObject *c_traceobj; 271 272 PyObject *curexc_type; 273 PyObject *curexc_value; 274 PyObject *curexc_traceback; 275 276 PyObject *exc_type; 277 PyObject *exc_value; 278 PyObject *exc_traceback; 279 280 PyObject *dict; /* Stores per-thread state */ 281 282 /* tick_counter is incremented whenever the check_interval ticker 283 * reaches zero. The purpose is to give a useful measure of the number 284 * of interpreted bytecode instructions in a given thread. This 285 * extremely lightweight statistic collector may be of interest to 286 * profilers (like psyco.jit()), although nothing in the core uses it. 287 */ 288 int tick_counter; 289 290 int gilstate_counter; 291 292 PyObject *async_exc; /* Asynchronous exception to raise */ 293 long thread_id; /* Thread id where this tstate was created */ 294 295 /* XXX signal handlers should also be here */ IsFor(int majorVersion,int minorVersion)296 static bool IsFor(int majorVersion, int minorVersion) { 297 return majorVersion == 2 && (minorVersion >= 5 && minorVersion <= 7); 298 } 299 IsFor(PythonVersion version)300 static bool IsFor(PythonVersion version) { 301 return version >= PythonVersion_25 && version <= PythonVersion_27; 302 } 303 }; 304 305 class PyThreadState_30_33 : public PyThreadState { 306 public: 307 PyThreadState *next; 308 PyInterpreterState *interp; 309 310 PyFrameObjectBaseUpTo39 *frame; 311 int recursion_depth; 312 char overflowed; /* The stack has overflowed. Allow 50 more calls 313 to handle the runtime error. */ 314 char recursion_critical; /* The current calls must not cause 315 a stack overflow. */ 316 /* 'tracing' keeps track of the execution depth when tracing/profiling. 317 This is to prevent the actual trace/profile code from being recorded in 318 the trace/profile. */ 319 int tracing; 320 int use_tracing; 321 322 Py_tracefunc c_profilefunc; 323 Py_tracefunc c_tracefunc; 324 PyObject *c_profileobj; 325 PyObject *c_traceobj; 326 327 PyObject *curexc_type; 328 PyObject *curexc_value; 329 PyObject *curexc_traceback; 330 331 PyObject *exc_type; 332 PyObject *exc_value; 333 PyObject *exc_traceback; 334 335 PyObject *dict; /* Stores per-thread state */ 336 337 /* tick_counter is incremented whenever the check_interval ticker 338 * reaches zero. The purpose is to give a useful measure of the number 339 * of interpreted bytecode instructions in a given thread. This 340 * extremely lightweight statistic collector may be of interest to 341 * profilers (like psyco.jit()), although nothing in the core uses it. 342 */ 343 int tick_counter; 344 345 int gilstate_counter; 346 347 PyObject *async_exc; /* Asynchronous exception to raise */ 348 long thread_id; /* Thread id where this tstate was created */ 349 350 /* XXX signal handlers should also be here */ IsFor(int majorVersion,int minorVersion)351 static bool IsFor(int majorVersion, int minorVersion) { 352 return majorVersion == 3 && (minorVersion >= 0 && minorVersion <= 3); 353 } 354 IsFor(PythonVersion version)355 static bool IsFor(PythonVersion version) { 356 return version >= PythonVersion_30 && version <= PythonVersion_33; 357 } 358 }; 359 360 class PyThreadState_34_36 : public PyThreadState { 361 public: 362 PyThreadState *prev; 363 PyThreadState *next; 364 PyInterpreterState *interp; 365 366 PyFrameObjectBaseUpTo39 *frame; 367 int recursion_depth; 368 char overflowed; /* The stack has overflowed. Allow 50 more calls 369 to handle the runtime error. */ 370 char recursion_critical; /* The current calls must not cause 371 a stack overflow. */ 372 /* 'tracing' keeps track of the execution depth when tracing/profiling. 373 This is to prevent the actual trace/profile code from being recorded in 374 the trace/profile. */ 375 int tracing; 376 int use_tracing; 377 378 Py_tracefunc c_profilefunc; 379 Py_tracefunc c_tracefunc; 380 PyObject *c_profileobj; 381 PyObject *c_traceobj; 382 383 PyObject *curexc_type; 384 PyObject *curexc_value; 385 PyObject *curexc_traceback; 386 387 PyObject *exc_type; 388 PyObject *exc_value; 389 PyObject *exc_traceback; 390 391 PyObject *dict; /* Stores per-thread state */ 392 393 int gilstate_counter; 394 395 PyObject *async_exc; /* Asynchronous exception to raise */ 396 397 long thread_id; /* Thread id where this tstate was created */ 398 /* XXX signal handlers should also be here */ 399 IsFor(int majorVersion,int minorVersion)400 static bool IsFor(int majorVersion, int minorVersion) { 401 return majorVersion == 3 && minorVersion >= 4 && minorVersion <= 6; 402 } 403 IsFor(PythonVersion version)404 static bool IsFor(PythonVersion version) { 405 return version >= PythonVersion_34 && version <= PythonVersion_36; 406 } 407 }; 408 409 struct _PyErr_StackItem { 410 PyObject *exc_type, *exc_value, *exc_traceback; 411 struct _PyErr_StackItem *previous_item; 412 }; 413 414 415 class PyThreadState_37_38 : public PyThreadState { 416 public: 417 PyThreadState *prev; 418 PyThreadState *next; 419 PyInterpreterState *interp; 420 421 PyFrameObjectBaseUpTo39 *frame; 422 int recursion_depth; 423 char overflowed; /* The stack has overflowed. Allow 50 more calls 424 to handle the runtime error. */ 425 char recursion_critical; /* The current calls must not cause 426 a stack overflow. */ 427 /* 'tracing' keeps track of the execution depth when tracing/profiling. 428 This is to prevent the actual trace/profile code from being recorded in 429 the trace/profile. */ 430 int stackcheck_counter; 431 432 int tracing; 433 int use_tracing; 434 435 Py_tracefunc c_profilefunc; 436 Py_tracefunc c_tracefunc; 437 PyObject *c_profileobj; 438 PyObject *c_traceobj; 439 440 PyObject *curexc_type; 441 PyObject *curexc_value; 442 PyObject *curexc_traceback; 443 444 _PyErr_StackItem exc_state; 445 _PyErr_StackItem *exc_info; 446 447 PyObject *dict; /* Stores per-thread state */ 448 449 int gilstate_counter; 450 451 PyObject *async_exc; /* Asynchronous exception to raise */ 452 453 unsigned long thread_id; /* Thread id where this tstate was created */ 454 IsFor(int majorVersion,int minorVersion)455 static bool IsFor(int majorVersion, int minorVersion) { 456 return majorVersion == 3 && (minorVersion == 7 || minorVersion == 8); 457 } 458 IsFor(PythonVersion version)459 static bool IsFor(PythonVersion version) { 460 return version == PythonVersion_37 || version == PythonVersion_38; 461 } 462 }; 463 464 // i.e.: https://github.com/python/cpython/blob/master/Include/cpython/pystate.h 465 class PyThreadState_39 : public PyThreadState { 466 public: 467 PyThreadState *prev; 468 PyThreadState *next; 469 PyInterpreterState *interp; 470 471 PyFrameObjectBaseUpTo39 *frame; 472 int recursion_depth; 473 char overflowed; /* The stack has overflowed. Allow 50 more calls 474 to handle the runtime error. */ 475 int stackcheck_counter; 476 477 int tracing; 478 int use_tracing; 479 480 Py_tracefunc c_profilefunc; 481 Py_tracefunc c_tracefunc; 482 PyObject *c_profileobj; 483 PyObject *c_traceobj; 484 485 PyObject *curexc_type; 486 PyObject *curexc_value; 487 PyObject *curexc_traceback; 488 489 _PyErr_StackItem exc_state; 490 _PyErr_StackItem *exc_info; 491 492 PyObject *dict; /* Stores per-thread state */ 493 494 int gilstate_counter; 495 496 PyObject *async_exc; /* Asynchronous exception to raise */ 497 498 unsigned long thread_id; /* Thread id where this tstate was created */ 499 IsFor(int majorVersion,int minorVersion)500 static bool IsFor(int majorVersion, int minorVersion) { 501 return majorVersion == 3 && minorVersion == 9; 502 } 503 IsFor(PythonVersion version)504 static bool IsFor(PythonVersion version) { 505 return version == PythonVersion_39; 506 } 507 }; 508 509 typedef struct _cframe { 510 /* This struct will be threaded through the C stack 511 * allowing fast access to per-thread state that needs 512 * to be accessed quickly by the interpreter, but can 513 * be modified outside of the interpreter. 514 * 515 * WARNING: This makes data on the C stack accessible from 516 * heap objects. Care must be taken to maintain stack 517 * discipline and make sure that instances of this struct cannot 518 * accessed outside of their lifetime. 519 */ 520 int use_tracing; 521 struct _cframe *previous; 522 } CFrame; 523 524 // i.e.: https://github.com/python/cpython/blob/master/Include/cpython/pystate.h 525 class PyThreadState_310 : public PyThreadState { 526 public: 527 PyThreadState *prev; 528 PyThreadState *next; 529 PyInterpreterState *interp; 530 531 PyFrameObject310 *frame; 532 int recursion_depth; 533 int recursion_headroom; /* Allow 50 more calls to handle any errors. */ 534 int stackcheck_counter; 535 536 /* 'tracing' keeps track of the execution depth when tracing/profiling. 537 This is to prevent the actual trace/profile code from being recorded in 538 the trace/profile. */ 539 int tracing; 540 541 /* Pointer to current CFrame in the C stack frame of the currently, 542 * or most recently, executing _PyEval_EvalFrameDefault. */ 543 CFrame *cframe; 544 545 546 Py_tracefunc c_profilefunc; 547 Py_tracefunc c_tracefunc; 548 PyObject *c_profileobj; 549 PyObject *c_traceobj; 550 551 PyObject *curexc_type; 552 PyObject *curexc_value; 553 PyObject *curexc_traceback; 554 555 _PyErr_StackItem exc_state; 556 _PyErr_StackItem *exc_info; 557 558 PyObject *dict; /* Stores per-thread state */ 559 560 int gilstate_counter; 561 562 PyObject *async_exc; /* Asynchronous exception to raise */ 563 564 unsigned long thread_id; /* Thread id where this tstate was created */ 565 IsFor(int majorVersion,int minorVersion)566 static bool IsFor(int majorVersion, int minorVersion) { 567 return majorVersion == 3 && minorVersion == 10; 568 } 569 IsFor(PythonVersion version)570 static bool IsFor(PythonVersion version) { 571 return version == PythonVersion_310; 572 } 573 }; 574 575 class PyIntObject : public PyObject { 576 public: 577 long ob_ival; 578 }; 579 580 class Py3kLongObject : public PyVarObject { 581 public: 582 DWORD ob_digit[1]; 583 }; 584 585 class PyOldStyleClassObject : public PyObject { 586 public: 587 PyObject *cl_bases; /* A tuple of class objects */ 588 PyObject *cl_dict; /* A dictionary */ 589 PyObject *cl_name; /* A string */ 590 /* The following three are functions or nullptr */ 591 PyObject *cl_getattr; 592 PyObject *cl_setattr; 593 PyObject *cl_delattr; 594 }; 595 596 class PyInstanceObject : public PyObject { 597 public: 598 PyOldStyleClassObject *in_class; /* The class object */ 599 PyObject *in_dict; /* A dictionary */ 600 PyObject *in_weakreflist; /* List of weak references */ 601 }; 602 603 #endif 604