-
Notifications
You must be signed in to change notification settings - Fork 3
/
example_basic.py
121 lines (94 loc) · 3.08 KB
/
example_basic.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# Example to show basic usage.
# The first version calls the main function with the run state
# while the second version does the same with the memory state
# by symbol resolution with some additional access tests.
# A third version (commented out) shows how to write an executable.
from __future__ import print_function
from tinycc import TinyCC
from ctypes import (CFUNCTYPE, c_int, c_void_p, Structure, c_ubyte,
POINTER, c_char, create_string_buffer, cast)
C_CODE = '''
#include <stdio.h>
/* a struct with some bytes and a length */
typedef struct Test {
int length;
unsigned char *bytes;
} Test;
/* some globals */
#ifdef STANDALONE
Test test = {10, "standalone"};
#else
Test test = {26, "abcdefghijklmnopqrstuvwxyz"};
#endif
int value = 12345;
int main(int argc, char **argv) {
int i;
char **pos = argv;
printf("Hello Python world from C!\n");
/* list arguments */
for (i=0; i<argc; ++i, ++pos) {
printf("arg %d: %s\n", i, *pos);
}
/* byte printing the hard way ;) */
printf("test.value: '");
for (i=0; i<test.length; ++i)
printf("%c", *(test.bytes+i));
printf("'");
if (*test.bytes == 'a')
printf(" - not so impressive.\n");
else if (*test.bytes == 's')
printf(" - ok.\n");
else
printf(" - Busted!\n");
return 0;
}
'''
# reassemble struct Test
class Test(Structure):
_fields_ = [('length', c_int),
('_bytes', c_void_p)]
@property
def bytes(self):
return bytearray((c_ubyte * self.length).from_address(self._bytes))
@bytes.setter
def bytes(self, bytes):
self._saved_ref = (c_ubyte * len(bytes))()
self._saved_ref[:] = bytes
self._bytes = cast(self._saved_ref, c_void_p)
self.length = len(bytes)
if __name__ == '__main__':
tcc = TinyCC()
# 1st version - simple direct run of main function
print('simple "run" state:')
state = tcc.create_state('run')
state.compile(C_CODE)
result = state.run(['stuff', 'from', 'the', 'cmdline'])
print('result:', result)
print()
# 2nd version - more complex run via symbols
print('"memory" state with symbol access:')
state = tcc.create_state() # defaults to 'memory'
state.compile(C_CODE)
state.relocate()
# resolve symbols
main = state.get_symbol('main', CFUNCTYPE(c_int, c_int, c_void_p))
test = state.get_symbol('test', Test)
value = state.get_symbol('value', c_int)
# alter test.bytes
test.bytes = bytearray(b'Python was here...')
# prepare main arguments
arguments = [b'this', b'is', b'more', b'interactive...']
argc = len(arguments)
argv = (POINTER(c_char) * argc)()
argv[:] = [create_string_buffer(s) for s in arguments]
# call main
result = main(argc, argv)
print('result:', result)
# read exported globals
print('global "test.bytes"', repr(test.bytes))
print('global "value":', repr(value))
# 3rd version - write an executable
#state = tcc.create_state('exe')
#state.define('STANDALONE')
#state.compile(C_CODE)
#state.write_file('hello_world')