-
Notifications
You must be signed in to change notification settings - Fork 0
/
test.cpp
155 lines (130 loc) · 5.18 KB
/
test.cpp
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include "PyVariable.h"
#include "PyException.h"
PyObject* helloFromC(PyObject*,PyObject*);
void yarrFromC(PyVariable);
PyVariable fastSum(PyVariable);
int main(){
/* First step is always to Initialize the Python interpreter itself
* Then you can start playing with PyVariable
*/
Py_Initialize();
PyVariable a,b;
a = 12.32; // You can assign most "C" values without problem to a variable
a = "Hello"; // And reassing to something else
b = " World!";
b = a + b; // This calls __add__, so you should be able to
// add and multiply most stuff
printf("%s\n",b.c_str()); // Hello World!
// You can access dictionnary items _AND_ attributes with
// the [] operator. Accessing a dict's attributes requires
// using o.getattr(..) directly
// If a PyVariable is a function, you can call it normally:
// foo()
// here we call b.upper()
b = b["upper"]();
PyVariable c = 2;
// as said earlier, this is just like "string"*n_repetitions in Python
b = b*c;
printf("b = %s\n",b.c_str()); // HELLO WORLD!HELLO WORLD!
// You can also evaluate Python code, such as handy lambda's
// quite easily
PyVariable foo = PyVariable::exec("lambda x:x**2");
// Note that, as in Python, functions and types and classes are
// variables. Also, and that's quite important, notice how earlier
// we did:
// b = b["upper"]()
// b["upper"] isn't just a function object. Somehow Python devs have
// hacked a brilliant way to attach an object to it's methods, so,
// b["upper"] can be called, like a callback, and the PyObject* method
// will "remember" that it is "b" that is the `self` argument when called.
// One can easily grab builtin functions:
PyVariable len = PyVariable::exec("len");
int b_len = len(b); //len(b) returns a PyVariable, but those
// can be cast directly to most numeric and string types
printf("len(b) -> %d\n",b_len);// 24
// You can call functions that take up to 3 arguments
// normally too. Anything (any "C" type) you can build a PyVariable with
// can be used as an argument.
printf("foo(12) -> %s\n",foo(12).c_str()); // 144
foo = PyVariable::exec("lambda x,y:x+y");
printf("foo(28,14) -> %s\n",foo(28,14).c_str());// 42
// You can also pass PyVariables as locals in an evaluation context
a = 32;
PyVariable inner_z = 68;
// Syntax is exec(command, comma separated variable names, PyVariable* ...)
b = PyVariable::exec("foo(a,z)","a,z,foo",&a,&inner_z,&foo);
printf("foo(32,68) -> %s\n",b.c_str());// 42
// You can creat dict's, and tuples and lists
b = PyVariable::dict();
// Since we don't want to mess with temporary values and incomplete
// map keys, to set a dictionnary item, one must use the setitem method
b.setitem("Yet another","test");
printf("b = %s\n",b.c_str()); // {'Yet another': 'test'}
// Another way to access an attribute, and in case you have a dictionnary at hand
// is to use getattr.
PyVariable hasK = b.getattr("has_key")("Yet another");
printf("b.has_key('Yet another') -> %s\n",hasK.c_str()); // True
// You can even push the heresy farther and create "Python" functions
// from proper C functions.
b = helloFromC;
b(); // Ahoyhoy from C!
b("Some",-32,"Arguments");
// note that helloFromC is a C function defined as
// PyObject* helloFromC(PyObject *self, PyObject *args)
b = yarrFromC;
b(142);// Yarr! from C with args (142,)
b(); // Yarr! from C with args ()
// here, yarrFromC is defined as:
// void yarrFromC(PyVariable args)
// args will always be a tuple containing the arguments
a = "Foo ";
foo = "Bar!";
// Remember how we could pass PyVariables as variables to Python?
// Well our "wrapper" to the C function yarrFromC can as well be passed
// to Python!
b = PyVariable::exec("func(a,b)","a,b,func",&a,&foo,&b);
// Enough with functions, creating maps and dictionnaries on the fly is always
// fun! The `setitem` method returns a reference to the dictionnary being handled,
// therefore allowing chaining pushes.
PyVariable d = PyVariable::dict()
.setitem("Key 1",42)
.setitem("Key 2","Value 2")
.setitem("Other key",yarrFromC);
printf("%s\n",d.c_str());
// {'Key 1': 42, 'Key 2': 'Value 2', 'Other key': <_pyvar_functype_void_pv object at 0x...>}
// You can also build lists on the fly:
PyVariable l = PyVariable::list()
.append("Bonzai")
.append(9001)
.append(a+foo, 2);
printf("%s\n",l.c_str()); // ['Bonzai', 9001, 'Foo Bar!', 'Foo Bar!']
// All in all, these are the function types you can pass to Python:
// `PyObject* (*)(PyObject* self,PyObject* args)`
// `void (*)(PyVariable args)`
// `PyVariable (*)(PyVariable args)`
// More to come! such as directly calling functions with more than 3 arguments ;)
return 1;
}
PyObject*
helloFromC(PyObject *self, PyObject *args)
{
printf("Ahoyhoy from C! %s\n",PyVariable(args).c_str());
return Py_BuildValue("i", 0);
}
void
yarrFromC(PyVariable args){
printf("Yarr! from C with args %s\n",args.c_str());
}
PyVariable
fastSum(PyVariable args){
args = args[0];
if (PySequence_Check(args.get())){
int sum = 0;
int len = args["__len__"]();
for (int i=0;i<len;++i){
sum+=args[i].c_int();
}
return sum;
}
return 0;
}