1 /* ****************************************************************************
2 *
3 * Copyright (c) Microsoft Corporation.
4 *
5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
6 * copy of the license can be found in the License.html file at the root of this distribution. If
7 * you cannot locate the Apache License, Version 2.0, please send an email to
8 * vspython@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
9 * by the terms of the Apache License, Version 2.0.
10 *
11 * You must not remove this notice, or any other, from this software.
12 *
13 * ***************************************************************************/
14
15 #ifndef __PYTHON_H__
16 #define __PYTHON_H__
17 #include <string.h>
18
19 // must be kept in sync with PythonLanguageVersion.cs
20 enum PythonVersion {
21 PythonVersion_Unknown,
22 PythonVersion_25 = 0x0205,
23 PythonVersion_26 = 0x0206,
24 PythonVersion_27 = 0x0207,
25 PythonVersion_30 = 0x0300,
26 PythonVersion_31 = 0x0301,
27 PythonVersion_32 = 0x0302,
28 PythonVersion_33 = 0x0303,
29 PythonVersion_34 = 0x0304
30 };
31
32
33 // defines limited header of Python API for compatible access across a number of Pythons.
34
35 class PyTypeObject;
36 class PyThreadState;
37
38 #define PyObject_HEAD \
39 size_t ob_refcnt; \
40 PyTypeObject *ob_type;
41
42 #define PyObject_VAR_HEAD \
43 PyObject_HEAD \
44 size_t ob_size; /* Number of items in variable part */
45
46 class PyObject {
47 public:
48 PyObject_HEAD
49 };
50
51 class PyVarObject : public PyObject {
52 public:
53 size_t ob_size; /* Number of items in variable part */
54 };
55
56 // 2.4 - 2.7 compatible
57 class PyCodeObject25_27 : public PyObject {
58 public:
59 int co_argcount; /* #arguments, except *args */
60 int co_nlocals; /* #local variables */
61 int co_stacksize; /* #entries needed for evaluation stack */
62 int co_flags; /* CO_..., see below */
63 PyObject *co_code; /* instruction opcodes */
64 PyObject *co_consts; /* list (constants used) */
65 PyObject *co_names; /* list of strings (names used) */
66 PyObject *co_varnames; /* tuple of strings (local variable names) */
67 PyObject *co_freevars; /* tuple of strings (free variable names) */
68 PyObject *co_cellvars; /* tuple of strings (cell variable names) */
69 /* The rest doesn't count for hash/cmp */
70 PyObject *co_filename; /* string (where it was loaded from) */
71 PyObject *co_name; /* string (name, for reference) */
72 int co_firstlineno; /* first source line number */
73 PyObject *co_lnotab; /* string (encoding addr<->lineno mapping) */
74
IsFor(int majorVersion,int minorVersion)75 static bool IsFor(int majorVersion, int minorVersion) {
76 return majorVersion == 2 && (minorVersion >= 5 && minorVersion <= 7);
77 }
78
IsFor(PythonVersion version)79 static bool IsFor(PythonVersion version) {
80 return version >= PythonVersion_25 && version <= PythonVersion_27;
81 }
82 };
83
84 // 3.0-3.2
85 class PyCodeObject30_32 : public PyObject {
86 public:
87 int co_argcount; /* #arguments, except *args */
88 int co_kwonlyargcount; /* #keyword only arguments */
89 int co_nlocals; /* #local variables */
90 int co_stacksize; /* #entries needed for evaluation stack */
91 int co_flags; /* CO_..., see below */
92 PyObject *co_code; /* instruction opcodes */
93 PyObject *co_consts; /* list (constants used) */
94 PyObject *co_names; /* list of strings (names used) */
95 PyObject *co_varnames; /* tuple of strings (local variable names) */
96 PyObject *co_freevars; /* tuple of strings (free variable names) */
97 PyObject *co_cellvars; /* tuple of strings (cell variable names) */
98 /* The rest doesn't count for hash or comparisons */
99 PyObject *co_filename; /* unicode (where it was loaded from) */
100 PyObject *co_name; /* unicode (name, for reference) */
101 int co_firstlineno; /* first source line number */
102 PyObject *co_lnotab; /* string (encoding addr<->lineno mapping) */
103 void *co_zombieframe; /* for optimization only (see frameobject.c) */
104
IsFor(int majorVersion,int minorVersion)105 static bool IsFor(int majorVersion, int minorVersion) {
106 return majorVersion == 3 && (minorVersion >= 0 && minorVersion <= 2);
107 }
108
IsFor(PythonVersion version)109 static bool IsFor(PythonVersion version) {
110 return version >= PythonVersion_30 && version <= PythonVersion_32;
111 }
112 };
113
114 // 3.3-3.4
115 class PyCodeObject33_34 : public PyObject {
116 public:
117 int co_argcount; /* #arguments, except *args */
118 int co_kwonlyargcount; /* #keyword only arguments */
119 int co_nlocals; /* #local variables */
120 int co_stacksize; /* #entries needed for evaluation stack */
121 int co_flags; /* CO_..., see below */
122 PyObject *co_code; /* instruction opcodes */
123 PyObject *co_consts; /* list (constants used) */
124 PyObject *co_names; /* list of strings (names used) */
125 PyObject *co_varnames; /* tuple of strings (local variable names) */
126 PyObject *co_freevars; /* tuple of strings (free variable names) */
127 PyObject *co_cellvars; /* tuple of strings (cell variable names) */
128 /* The rest doesn't count for hash or comparisons */
129 unsigned char *co_cell2arg; /* Maps cell vars which are arguments. */
130 PyObject *co_filename; /* unicode (where it was loaded from) */
131 PyObject *co_name; /* unicode (name, for reference) */
132 int co_firstlineno; /* first source line number */
133 PyObject *co_lnotab; /* string (encoding addr<->lineno mapping) */
134 void *co_zombieframe; /* for optimization only (see frameobject.c) */
135
IsFor(int majorVersion,int minorVersion)136 static bool IsFor(int majorVersion, int minorVersion) {
137 return majorVersion == 3 && (minorVersion >= 3 && minorVersion <= 4);
138 }
139
IsFor(PythonVersion version)140 static bool IsFor(PythonVersion version) {
141 return version >= PythonVersion_33 && version <= PythonVersion_34;
142 }
143 };
144
145 // 2.5 - 3.1
146 class PyFunctionObject : public PyObject {
147 public:
148 PyObject *func_code; /* A code object */
149 };
150
151 // 2.5 - 2.7 compatible
152 class PyStringObject : public PyVarObject {
153 public:
154 long ob_shash;
155 int ob_sstate;
156 char ob_sval[1];
157
158 /* Invariants:
159 * ob_sval contains space for 'ob_size+1' elements.
160 * ob_sval[ob_size] == 0.
161 * ob_shash is the hash of the string or -1 if not computed yet.
162 * ob_sstate != 0 iff the string object is in stringobject.c's
163 * 'interned' dictionary; in this case the two references
164 * from 'interned' to this object are *not counted* in ob_refcnt.
165 */
166 };
167
168 // 2.4 - 3.2 compatible
169 typedef struct {
170 PyObject_HEAD
171 size_t length; /* Length of raw Unicode data in buffer */
172 wchar_t *str; /* Raw Unicode buffer */
173 long hash; /* Hash value; -1 if not set */
174 } PyUnicodeObject;
175
176 // 2.4 - 3.4 compatible
177 class PyFrameObject : public PyVarObject {
178 public:
179 PyFrameObject *f_back; /* previous frame, or NULL */
180 PyObject *f_code; /* code segment */
181 PyObject *f_builtins; /* builtin symbol table (PyDictObject) */
182 PyObject *f_globals; /* global symbol table (PyDictObject) */
183 PyObject *f_locals; /* local symbol table (any mapping) */
184 PyObject **f_valuestack; /* points after the last local */
185 /* Next free slot in f_valuestack. Frame creation sets to f_valuestack.
186 Frame evaluation usually NULLs it, but a frame that yields sets it
187 to the current stack top. */
188 PyObject **f_stacktop;
189 PyObject *f_trace; /* Trace function */
190 PyObject *f_exc_type, *f_exc_value, *f_exc_traceback;
191 };
192
193 #define CO_MAXBLOCKS 20
194 typedef struct {
195 int b_type; /* what kind of block this is */
196 int b_handler; /* where to jump to find handler */
197 int b_level; /* value stack level to pop to */
198 } PyTryBlock;
199
200 class PyFrameObject25_33 : public PyFrameObject {
201 public:
202 PyThreadState* f_tstate;
203 int f_lasti; /* Last instruction if called */
204 /* As of 2.3 f_lineno is only valid when tracing is active (i.e. when
205 f_trace is set) -- at other times use PyCode_Addr2Line instead. */
206 int f_lineno; /* Current line number */
207 int f_iblock; /* index in f_blockstack */
208 PyTryBlock f_blockstack[CO_MAXBLOCKS]; /* for try and loop blocks */
209 PyObject *f_localsplus[1]; /* locals+stack, dynamically sized */
210
IsFor(int majorVersion,int minorVersion)211 static bool IsFor(int majorVersion, int minorVersion) {
212 return majorVersion == 2 && (minorVersion >= 5 && minorVersion <= 7) ||
213 majorVersion == 3 && (minorVersion >= 0 && minorVersion <= 3);
214 }
215 };
216
217 class PyFrameObject34 : public PyFrameObject {
218 public:
219 /* Borrowed reference to a generator, or NULL */
220 PyObject *f_gen;
221
222 int f_lasti; /* Last instruction if called */
223 /* As of 2.3 f_lineno is only valid when tracing is active (i.e. when
224 f_trace is set) -- at other times use PyCode_Addr2Line instead. */
225 int f_lineno; /* Current line number */
226 int f_iblock; /* index in f_blockstack */
227 char f_executing; /* whether the frame is still executing */
228 PyTryBlock f_blockstack[CO_MAXBLOCKS]; /* for try and loop blocks */
229 PyObject *f_localsplus[1]; /* locals+stack, dynamically sized */
230
IsFor(int majorVersion,int minorVersion)231 static bool IsFor(int majorVersion, int minorVersion) {
232 return majorVersion == 3 && minorVersion == 4;
233 }
234 };
235
236
237 typedef void (*destructor)(PyObject *);
238
239 // 2.4 - 3.4
240 class PyMethodDef {
241 public:
242 char *ml_name; /* The name of the built-in function/method */
243 };
244
245
246 //
247 // 2.4 - 3.4, 2.4 has different compat in 64-bit but we don't support any of the released 64-bit platforms (which includes only IA-64)
248 // While these are compatible there are fields only available on later versions.
249 class PyTypeObject : public PyVarObject {
250 public:
251 const char *tp_name; /* For printing, in format "<module>.<name>" */
252 size_t tp_basicsize, tp_itemsize; /* For allocation */
253
254 /* Methods to implement standard operations */
255
256 destructor tp_dealloc;
257 void* tp_print;
258 void* tp_getattr;
259 void* tp_setattr;
260 void* tp_compare;
261 void* tp_repr;
262
263 /* Method suites for standard classes */
264
265 void *tp_as_number;
266 void*tp_as_sequence;
267 void*tp_as_mapping;
268
269 /* More standard operations (here for binary compatibility) */
270
271 void* tp_hash;
272 void* tp_call;
273 void* tp_str;
274 void* tp_getattro;
275 void* tp_setattro;
276
277 /* Functions to access object as input/output buffer */
278 void*tp_as_buffer;
279
280 /* Flags to define presence of optional/expanded features */
281 long tp_flags;
282
283 const char *tp_doc; /* Documentation string */
284
285 /* Assigned meaning in release 2.0 */
286 /* call function for all accessible objects */
287 void* tp_traverse;
288
289 /* delete references to contained objects */
290 void* tp_clear;
291
292 /* Assigned meaning in release 2.1 */
293 /* rich comparisons */
294 void* tp_richcompare;
295
296 /* weak reference enabler */
297 size_t tp_weaklistoffset;
298
299 /* Added in release 2.2 */
300 /* Iterators */
301 void* tp_iter;
302 void* tp_iternext;
303
304 /* Attribute descriptor and subclassing stuff */
305 PyMethodDef *tp_methods;
306 struct PyMemberDef *tp_members;
307 struct PyGetSetDef *tp_getset;
308 struct _typeobject *tp_base;
309 PyObject *tp_dict;
310 void* tp_descr_get;
311 void* tp_descr_set;
312 size_t tp_dictoffset;
313 void* tp_init;
314 void* tp_alloc;
315 void* tp_new;
316 void* tp_free; /* Low-level free-memory routine */
317 void* tp_is_gc; /* For PyObject_IS_GC */
318 PyObject *tp_bases;
319 PyObject *tp_mro; /* method resolution order */
320 PyObject *tp_cache;
321 PyObject *tp_subclasses;
322 PyObject *tp_weaklist;
323 void* tp_del;
324
325 /* Type attribute cache version tag. Added in version 2.6 */
326 unsigned int tp_version_tag;
327 };
328
329 // 2.4 - 3.4
330 class PyTupleObject : public PyVarObject {
331 public:
332 PyObject *ob_item[1];
333
334 /* ob_item contains space for 'ob_size' elements.
335 * Items must normally not be NULL, except during construction when
336 * the tuple is not yet visible outside the function that builds it.
337 */
338 };
339
340 // 2.4 - 3.4
341 class PyCFunctionObject : public PyObject {
342 public:
343 PyMethodDef *m_ml; /* Description of the C function to call */
344 PyObject *m_self; /* Passed as 'self' arg to the C func, can be NULL */
345 PyObject *m_module; /* The __module__ attribute, can be anything */
346 };
347
348 typedef int (*Py_tracefunc)(PyObject *, PyFrameObject *, int, PyObject *);
349
350 #define PyTrace_CALL 0
351 #define PyTrace_EXCEPTION 1
352 #define PyTrace_LINE 2
353 #define PyTrace_RETURN 3
354 #define PyTrace_C_CALL 4
355 #define PyTrace_C_EXCEPTION 5
356 #define PyTrace_C_RETURN 6
357
358 class PyInterpreterState {
359 };
360
361 class PyThreadState { };
362
363 class PyThreadState_25_27 : public PyThreadState {
364 public:
365 /* See Python/ceval.c for comments explaining most fields */
366
367 PyThreadState *next;
368 PyInterpreterState *interp;
369
370 PyFrameObject *frame;
371 int recursion_depth;
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 /* tick_counter is incremented whenever the check_interval ticker
394 * reaches zero. The purpose is to give a useful measure of the number
395 * of interpreted bytecode instructions in a given thread. This
396 * extremely lightweight statistic collector may be of interest to
397 * profilers (like psyco.jit()), although nothing in the core uses it.
398 */
399 int tick_counter;
400
401 int gilstate_counter;
402
403 PyObject *async_exc; /* Asynchronous exception to raise */
404 long thread_id; /* Thread id where this tstate was created */
405
406 /* XXX signal handlers should also be here */
IsFor(int majorVersion,int minorVersion)407 static bool IsFor(int majorVersion, int minorVersion) {
408 return majorVersion == 2 && (minorVersion >= 5 && minorVersion <= 7);
409 }
410
IsFor(PythonVersion version)411 static bool IsFor(PythonVersion version) {
412 return version >= PythonVersion_25 && version <= PythonVersion_27;
413 }
414 };
415
416 class PyThreadState_30_33 : public PyThreadState {
417 public:
418 PyThreadState *next;
419 PyInterpreterState *interp;
420
421 PyFrameObject *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 tracing;
431 int use_tracing;
432
433 Py_tracefunc c_profilefunc;
434 Py_tracefunc c_tracefunc;
435 PyObject *c_profileobj;
436 PyObject *c_traceobj;
437
438 PyObject *curexc_type;
439 PyObject *curexc_value;
440 PyObject *curexc_traceback;
441
442 PyObject *exc_type;
443 PyObject *exc_value;
444 PyObject *exc_traceback;
445
446 PyObject *dict; /* Stores per-thread state */
447
448 /* tick_counter is incremented whenever the check_interval ticker
449 * reaches zero. The purpose is to give a useful measure of the number
450 * of interpreted bytecode instructions in a given thread. This
451 * extremely lightweight statistic collector may be of interest to
452 * profilers (like psyco.jit()), although nothing in the core uses it.
453 */
454 int tick_counter;
455
456 int gilstate_counter;
457
458 PyObject *async_exc; /* Asynchronous exception to raise */
459 long thread_id; /* Thread id where this tstate was created */
460
461 /* XXX signal handlers should also be here */
IsFor(int majorVersion,int minorVersion)462 static bool IsFor(int majorVersion, int minorVersion) {
463 return majorVersion == 3 && (minorVersion >= 0 && minorVersion <= 3);
464 }
465
IsFor(PythonVersion version)466 static bool IsFor(PythonVersion version) {
467 return version >= PythonVersion_30 && version <= PythonVersion_33;
468 }
469 };
470
471 class PyThreadState_34 : public PyThreadState {
472 public:
473 PyThreadState *prev;
474 PyThreadState *next;
475 PyInterpreterState *interp;
476
477 PyFrameObject *frame;
478 int recursion_depth;
479 char overflowed; /* The stack has overflowed. Allow 50 more calls
480 to handle the runtime error. */
481 char recursion_critical; /* The current calls must not cause
482 a stack overflow. */
483 /* 'tracing' keeps track of the execution depth when tracing/profiling.
484 This is to prevent the actual trace/profile code from being recorded in
485 the trace/profile. */
486 int tracing;
487 int use_tracing;
488
489 Py_tracefunc c_profilefunc;
490 Py_tracefunc c_tracefunc;
491 PyObject *c_profileobj;
492 PyObject *c_traceobj;
493
494 PyObject *curexc_type;
495 PyObject *curexc_value;
496 PyObject *curexc_traceback;
497
498 PyObject *exc_type;
499 PyObject *exc_value;
500 PyObject *exc_traceback;
501
502 PyObject *dict; /* Stores per-thread state */
503
504 int gilstate_counter;
505
506 PyObject *async_exc; /* Asynchronous exception to raise */
507 long thread_id; /* Thread id where this tstate was created */
508
509 /* XXX signal handlers should also be here */
IsFor(int majorVersion,int minorVersion)510 static bool IsFor(int majorVersion, int minorVersion) {
511 return majorVersion == 3 && minorVersion == 4;
512 }
513
IsFor(PythonVersion version)514 static bool IsFor(PythonVersion version) {
515 return version == PythonVersion_34;
516 }
517 };
518
519 class PyIntObject : public PyObject {
520 public:
521 long ob_ival;
522 };
523
524 //class Py3kLongObject : public PyVarObject {
525 //public:
526 // DWORD ob_digit[1];
527 //};
528
529 class PyOldStyleClassObject : public PyObject {
530 public:
531 PyObject *cl_bases; /* A tuple of class objects */
532 PyObject *cl_dict; /* A dictionary */
533 PyObject *cl_name; /* A string */
534 /* The following three are functions or NULL */
535 PyObject *cl_getattr;
536 PyObject *cl_setattr;
537 PyObject *cl_delattr;
538 };
539
540 class PyInstanceObject : public PyObject {
541 public:
542 PyOldStyleClassObject *in_class; /* The class object */
543 PyObject *in_dict; /* A dictionary */
544 PyObject *in_weakreflist; /* List of weak references */
545 };
546
547 typedef const char* (*GetVersionFunc) ();
548
GetPythonVersion()549 static PythonVersion GetPythonVersion() {
550 GetVersionFunc versionFunc;
551 void *main_hndl = dlopen(NULL, 0x2);
552 *(void**)(&versionFunc) = dlsym(main_hndl, "Py_GetVersion");
553 if(versionFunc != NULL) {
554 const char* version = versionFunc();
555 if(version != NULL && strlen(version) >= 3 && version[1] == '.') {
556 if(version[0] == '2') {
557 switch(version[2]) {
558 case '5': return PythonVersion_25;
559 case '6': return PythonVersion_26;
560 case '7': return PythonVersion_27;
561 }
562 } else if(version[0] == '3') {
563 switch(version[2]) {
564 case '0': return PythonVersion_30;
565 case '1': return PythonVersion_31;
566 case '2': return PythonVersion_32;
567 case '3': return PythonVersion_33;
568 case '4': return PythonVersion_34;
569 }
570 }
571 }
572 }
573 return PythonVersion_Unknown;
574 }
575
576 #endif
577