···11+#include "pocketpy.h"
22+#include "pocketpy_c.h"
33+44+using namespace pkpy;
55+66+#define PKPY_STACK_SIZE 32
77+88+#define SAFEGUARD_OPEN try { \
99+1010+#define SAFEGUARD_CLOSE \
1111+ } catch(std::exception& e) { \
1212+ std::cerr << "ERROR: a std::exception " \
1313+ << "this probably means pocketpy itself has a bug!\n" \
1414+ << e.what() << "\n"; \
1515+ exit(2); \
1616+ } catch(...) { \
1717+ std::cerr << "ERROR: a unknown exception was thrown from " << __func__ \
1818+ << "\nthis probably means pocketpy itself has a bug!\n"; \
1919+ exit(2); \
2020+ }
2121+2222+2323+#define ERRHANDLER_OPEN SAFEGUARD_OPEN \
2424+ try { \
2525+ if (vm->c_data->size() > 0 && vm->c_data->top() == nullptr) \
2626+ return false; \
2727+2828+#define ERRHANDLER_CLOSE \
2929+ } catch( Exception e ) { \
3030+ vm->c_data->push(py_var(vm, e)); \
3131+ vm->c_data->push(NULL); \
3232+ return false; \
3333+ } \
3434+ SAFEGUARD_CLOSE \
3535+3636+3737+3838+class CVM : public VM {
3939+ public :
4040+4141+ ValueStackImpl<PKPY_STACK_SIZE>* c_data;
4242+ CVM(bool enable_os=true) : VM(enable_os) {
4343+ c_data = new ValueStackImpl<PKPY_STACK_SIZE>();
4444+ }
4545+4646+ ~CVM() {
4747+ c_data->clear();
4848+ delete c_data;
4949+ }
5050+};
5151+5252+5353+//for now I will unpack a tuple automatically, we may not want to handle
5454+//it this way, not sure
5555+//it is more lua like, but maybe not python like
5656+static void unpack_return(CVM* vm, PyObject* ret) {
5757+ if (is_type(ret, vm->tp_tuple)) {
5858+ Tuple& t = py_cast<Tuple&>(vm, ret);
5959+ for (int i = 0; i < t.size(); i++)
6060+ vm->c_data->push(t[i]);
6161+ } else if (ret == vm->None) {
6262+ //do nothing here
6363+ //having to pop the stack after every call that returns none is annoying
6464+ //lua does not do this
6565+ //
6666+ //so for now we will not push none on the stack when it is the sole thing returned
6767+ //if this becomes a problem we can change it
6868+ //
6969+ //you can still check if it returned none by comparing stack size before
7070+ //and after if you have to
7171+ } else
7272+ vm->c_data->push(ret);
7373+7474+}
7575+7676+7777+bool pkpy_clear_error(pkpy_vm* vm_handle, char** message) {
7878+ CVM* vm = (CVM*) vm_handle;
7979+ SAFEGUARD_OPEN
8080+8181+ if (vm->c_data->size() == 0 || vm->c_data->top() != nullptr)
8282+ return false;
8383+8484+ vm->c_data->pop();
8585+ Exception& e = py_cast<Exception&>(vm, vm->c_data->top());
8686+ if (message != nullptr)
8787+ *message = e.summary().c_str_dup();
8888+ else
8989+ std::cerr << "ERROR: " << e.summary() << "\n";
9090+9191+ vm->c_data->clear();
9292+ vm->callstack.clear();
9393+ vm->s_data.clear();
9494+ return true;
9595+9696+ SAFEGUARD_CLOSE
9797+}
9898+9999+void gc_marker_ex(CVM* vm) {
100100+ for(PyObject* obj: *vm->c_data) if(obj!=nullptr) OBJ_MARK(obj);
101101+}
102102+103103+104104+static void noop_output_handler(VM* vm, const Str& str) {
105105+ (void) vm;
106106+ (void) str;
107107+}
108108+109109+pkpy_vm* pkpy_vm_create(bool use_stdio, bool enable_os) {
110110+111111+ CVM* vm = new CVM(enable_os);
112112+ vm->c_data = new ValueStackImpl<PKPY_STACK_SIZE>();
113113+ vm->_gc_marker_ex = (void (*)(VM*)) gc_marker_ex;
114114+115115+ if (!use_stdio) {
116116+ vm->_stdout = noop_output_handler;
117117+ vm->_stderr = noop_output_handler;
118118+ }
119119+120120+ return (pkpy_vm*) vm;
121121+}
122122+123123+bool pkpy_vm_run(pkpy_vm* vm_handle, const char* source) {
124124+ CVM* vm = (CVM*) vm_handle;
125125+ ERRHANDLER_OPEN
126126+127127+ CodeObject_ code = vm->compile(source, "<c-bound>", EXEC_MODE);
128128+ PyObject* result = vm->_exec(code, vm->_main);
129129+130130+ //unpack_return(w, result);
131131+ //NOTE: it seems like vm->_exec should return whatever the last command it
132132+ //ran returned but instead it seems to pretty much always return None
133133+ //so I guess uncomment this line if that every changes
134134+135135+ return true;
136136+ ERRHANDLER_CLOSE
137137+}
138138+139139+void pkpy_vm_destroy(pkpy_vm* vm_handle) {
140140+ CVM* vm = (CVM*) vm_handle;
141141+ delete vm;
142142+}
143143+144144+static void propagate_if_errored(CVM* vm, ValueStackImpl<PKPY_STACK_SIZE>* stored_stack) {
145145+ try {
146146+ if (vm->c_data->size() == 0 || vm->c_data->top() != nullptr)
147147+ return;
148148+149149+ vm->c_data->pop();
150150+ Exception& e = py_cast<Exception&>(vm, vm->c_data->top());
151151+ vm->c_data->pop();
152152+153153+ vm->c_data = stored_stack;
154154+155155+ throw e;
156156+ } catch(Exception& e) {
157157+ throw;
158158+ } catch(...) {
159159+ std::cerr << "ERROR: a non pocketpy exeception was thrown "
160160+ << "this probably means pocketpy itself has a bug!\n";
161161+ exit(2);
162162+ }
163163+}
164164+165165+PyObject* c_function_wrapper(VM* vm, ArgsView args) {
166166+ LuaStyleFuncC f = py_cast<NativeFunc&>(vm, args[-2])._lua_f;
167167+ CVM* cvm = (CVM*) vm;
168168+169169+ //setup c stack
170170+ ValueStackImpl<PKPY_STACK_SIZE> local_stack;
171171+172172+ for (int i = 0; i < args.size(); i++)
173173+ local_stack.push(args[i]);
174174+175175+ ValueStackImpl<PKPY_STACK_SIZE>* stored_stack = cvm->c_data;
176176+ cvm->c_data = &local_stack;
177177+178178+ int retc = f(cvm);
179179+180180+ propagate_if_errored(cvm, stored_stack);
181181+ cvm->c_data = stored_stack;
182182+183183+ PyObject* ret = cvm->None;
184184+185185+ if (retc == 1)
186186+ ret = local_stack.top();
187187+ else if (retc > 1) {
188188+ Tuple t(retc);
189189+190190+ for (int i = 0; i < retc; i++) {
191191+ int stack_index = (local_stack.size() - retc) + i;
192192+ t[i] = local_stack.begin()[stack_index];
193193+ }
194194+195195+ ret = py_var(cvm, t);
196196+ }
197197+198198+ return ret;
199199+}
200200+201201+bool pkpy_push_function(pkpy_vm* vm_handle, pkpy_function f) {
202202+ CVM* vm = (CVM*) vm_handle;
203203+ ERRHANDLER_OPEN
204204+205205+ //TODO right now we just treat all c bound functions a varargs functions
206206+ //do we want to change that?
207207+ NativeFunc nf = NativeFunc(c_function_wrapper, -1, 0);
208208+ nf._lua_f = (LuaStyleFuncC) f;
209209+210210+ vm->c_data->push(py_var(vm, nf));
211211+212212+ return true;
213213+ ERRHANDLER_CLOSE
214214+}
215215+216216+bool pkpy_push_int(pkpy_vm* vm_handle, int value) {
217217+ CVM* vm = (CVM*) vm_handle;
218218+ ERRHANDLER_OPEN
219219+220220+ vm->c_data->push(py_var(vm, value));
221221+222222+ return true;
223223+ ERRHANDLER_CLOSE
224224+}
225225+226226+bool pkpy_push_float(pkpy_vm* vm_handle, double value) {
227227+ CVM* vm = (CVM*) vm_handle;
228228+ ERRHANDLER_OPEN
229229+ vm->c_data->push(py_var(vm, value));
230230+231231+ return true;
232232+ ERRHANDLER_CLOSE
233233+}
234234+235235+bool pkpy_push_bool(pkpy_vm* vm_handle, bool value) {
236236+ CVM* vm = (CVM*) vm_handle;
237237+ ERRHANDLER_OPEN
238238+ vm->c_data->push(py_var(vm, value));
239239+240240+ return true;
241241+ ERRHANDLER_CLOSE
242242+}
243243+244244+bool pkpy_push_string(pkpy_vm* vm_handle, const char* value) {
245245+ CVM* vm = (CVM*) vm_handle;
246246+ ERRHANDLER_OPEN
247247+ vm->c_data->push(py_var(vm, value));
248248+249249+ return true;
250250+ ERRHANDLER_CLOSE
251251+}
252252+253253+bool pkpy_push_stringn(pkpy_vm* vm_handle, const char* value, int length) {
254254+ CVM* vm = (CVM*) vm_handle;
255255+ ERRHANDLER_OPEN
256256+257257+ Str s = Str(value, length);
258258+ vm->c_data->push(py_var(vm, s));
259259+260260+ return true;
261261+ ERRHANDLER_CLOSE
262262+}
263263+264264+bool pkpy_push_voidp(pkpy_vm* vm_handle, void* value) {
265265+ CVM* vm = (CVM*) vm_handle;
266266+ ERRHANDLER_OPEN
267267+ vm->c_data->push(py_var(vm, value));
268268+269269+ return true;
270270+ ERRHANDLER_CLOSE
271271+}
272272+273273+bool pkpy_push_none(pkpy_vm* vm_handle) {
274274+ CVM* vm = (CVM*) vm_handle;
275275+ ERRHANDLER_OPEN
276276+ vm->c_data->push(vm->None);
277277+278278+ return true;
279279+ ERRHANDLER_CLOSE
280280+}
281281+282282+283283+284284+bool pkpy_set_global(pkpy_vm* vm_handle, const char* name) {
285285+ CVM* vm = (CVM*) vm_handle;
286286+ ERRHANDLER_OPEN
287287+288288+ vm->_main->attr().set(name, vm->c_data->top());
289289+290290+ vm->c_data->pop();
291291+292292+ return true;
293293+ ERRHANDLER_CLOSE
294294+}
295295+296296+//get global will also get bulitins
297297+bool pkpy_get_global(pkpy_vm* vm_handle, const char* name) {
298298+ CVM* vm = (CVM*) vm_handle;
299299+ ERRHANDLER_OPEN
300300+301301+ PyObject* o = vm->_main->attr().try_get(name);
302302+ if (o == nullptr) {
303303+ o = vm->builtins->attr().try_get(name);
304304+ if (o == nullptr)
305305+ throw Exception("NameError", "could not find requested global");
306306+ }
307307+308308+ vm->c_data->push(o);
309309+310310+ return true;
311311+ ERRHANDLER_CLOSE
312312+}
313313+314314+315315+bool pkpy_call(pkpy_vm* vm_handle, int argc) {
316316+ CVM* vm = (CVM*) vm_handle;
317317+ ERRHANDLER_OPEN
318318+319319+ int callable_index = vm->c_data->size() - argc - 1;
320320+321321+ PyObject* callable = vm->c_data->begin()[callable_index];
322322+323323+ vm->s_data.push(callable);
324324+ vm->s_data.push(PY_NULL);
325325+326326+ for (int i = 0; i < argc; i++)
327327+ vm->s_data.push(vm->c_data->begin()[callable_index + i + 1]);
328328+329329+ PyObject* o = vm->vectorcall(argc);
330330+331331+ vm->c_data->shrink(argc + 1);
332332+333333+ unpack_return(vm, o);
334334+335335+ return true;
336336+ ERRHANDLER_CLOSE
337337+}
338338+339339+bool pkpy_call_method(pkpy_vm* vm_handle, const char* name, int argc) {
340340+ CVM* vm = (CVM*) vm_handle;
341341+ ERRHANDLER_OPEN
342342+343343+ int self_index = vm->c_data->size() - argc - 1;
344344+ PyObject* self = vm->c_data->begin()[self_index];
345345+346346+ PyObject* callable = vm->get_unbound_method(self, name, &self);
347347+348348+ vm->s_data.push(callable);
349349+ vm->s_data.push(self);
350350+351351+ for (int i = 0; i < argc; i++)
352352+ vm->s_data.push(vm->c_data->begin()[self_index + i + 1]);
353353+354354+ PyObject* o = vm->vectorcall(argc);
355355+356356+ vm->c_data->shrink(argc + 1);
357357+358358+ unpack_return(vm, o);
359359+360360+ return true;
361361+ ERRHANDLER_CLOSE
362362+}
363363+364364+365365+366366+static int lua_to_cstack_index(int index, int size) {
367367+ if (index < 0)
368368+ index = size + index;
369369+ return index;
370370+}
371371+372372+bool pkpy_to_int(pkpy_vm* vm_handle, int index, int* ret) {
373373+ CVM* vm = (CVM*) vm_handle;
374374+ ERRHANDLER_OPEN
375375+376376+ index = lua_to_cstack_index(index, vm->c_data->size());
377377+378378+ PyObject* o = vm->c_data->begin()[index];
379379+380380+ if (!is_type(o, vm->tp_int))
381381+ throw Exception("TypeError", "pkpy_to_int on non int object");
382382+383383+ if (ret != nullptr)
384384+ *ret = py_cast<int>(vm, o);
385385+386386+ return true;
387387+ ERRHANDLER_CLOSE
388388+}
389389+390390+bool pkpy_to_float(pkpy_vm* vm_handle, int index, double* ret) {
391391+ CVM* vm = (CVM*) vm_handle;
392392+ ERRHANDLER_OPEN
393393+394394+ index = lua_to_cstack_index(index, vm->c_data->size());
395395+396396+ PyObject* o = vm->c_data->begin()[index];
397397+398398+ if (!is_type(o, vm->tp_float))
399399+ throw Exception("TypeError", "pkpy_to_float on non float object");
400400+401401+ if (ret != nullptr)
402402+ *ret = py_cast<double>(vm, o);
403403+404404+ return true;
405405+ ERRHANDLER_CLOSE
406406+}
407407+408408+bool pkpy_to_bool(pkpy_vm* vm_handle, int index, bool* ret) {
409409+ CVM* vm = (CVM*) vm_handle;
410410+ ERRHANDLER_OPEN
411411+412412+ index = lua_to_cstack_index(index, vm->c_data->size());
413413+414414+ PyObject* o = vm->c_data->begin()[index];
415415+ if (!is_type(o, vm->tp_bool))
416416+ throw Exception("TypeError", "pkpy_to_bool on non bool object");
417417+418418+ if (ret != nullptr)
419419+ *ret = py_cast<bool>(vm, o);
420420+421421+ return true;
422422+ ERRHANDLER_CLOSE
423423+}
424424+425425+bool pkpy_to_voidp(pkpy_vm* vm_handle, int index, void** ret) {
426426+ CVM* vm = (CVM*) vm_handle;
427427+ ERRHANDLER_OPEN
428428+429429+ index = lua_to_cstack_index(index, vm->c_data->size());
430430+431431+ PyObject* o = vm->c_data->begin()[index];
432432+ if (!is_type(o, VoidP::_type(vm)))
433433+ throw Exception("TypeError", "pkpy_to_voidp on non void* object");
434434+435435+ if (ret != nullptr)
436436+ *ret = py_cast<void*>(vm, o);
437437+438438+ return true;
439439+ ERRHANDLER_CLOSE
440440+}
441441+442442+bool pkpy_to_string(pkpy_vm* vm_handle, int index, char** ret) {
443443+ CVM* vm = (CVM*) vm_handle;
444444+ ERRHANDLER_OPEN
445445+446446+ index = lua_to_cstack_index(index, vm->c_data->size());
447447+448448+ PyObject* o = vm->c_data->begin()[index];
449449+ if (!is_type(o, vm->tp_str))
450450+ throw Exception("TypeError", "pkpy_to_string on non string object");
451451+452452+ if (ret != nullptr) {
453453+ Str& s = py_cast<Str&>(vm, o);
454454+ *ret = s.c_str_dup();
455455+ }
456456+457457+ return true;
458458+ ERRHANDLER_CLOSE
459459+}
460460+461461+bool pkpy_to_stringn(pkpy_vm* vm_handle, int index, const char** ret, int* size) {
462462+ CVM* vm = (CVM*) vm_handle;
463463+ ERRHANDLER_OPEN
464464+465465+ index = lua_to_cstack_index(index, vm->c_data->size());
466466+467467+ PyObject* o = vm->c_data->begin()[index];
468468+ if (ret != nullptr) {
469469+ std::string_view sv = py_cast<Str&>(vm, o).sv();
470470+ *ret = sv.data();
471471+ *size = sv.size();
472472+ }
473473+474474+ return true;
475475+ ERRHANDLER_CLOSE
476476+}
477477+478478+479479+bool pkpy_is_int(pkpy_vm* vm_handle, int index) {
480480+ CVM* vm = (CVM*) vm_handle;
481481+ index = lua_to_cstack_index(index, vm->c_data->size());
482482+ PyObject* o = vm->c_data->begin()[index];
483483+484484+ return is_type(o, vm->tp_int);
485485+}
486486+bool pkpy_is_float(pkpy_vm* vm_handle, int index) {
487487+ CVM* vm = (CVM*) vm_handle;
488488+ index = lua_to_cstack_index(index, vm->c_data->size());
489489+ PyObject* o = vm->c_data->begin()[index];
490490+491491+ return is_type(o, vm->tp_float);
492492+}
493493+bool pkpy_is_bool(pkpy_vm* vm_handle, int index) {
494494+ CVM* vm = (CVM*) vm_handle;
495495+ index = lua_to_cstack_index(index, vm->c_data->size());
496496+ PyObject* o = vm->c_data->begin()[index];
497497+498498+ return is_type(o, vm->tp_bool);
499499+}
500500+bool pkpy_is_string(pkpy_vm* vm_handle, int index) {
501501+ CVM* vm = (CVM*) vm_handle;
502502+ index = lua_to_cstack_index(index, vm->c_data->size());
503503+ PyObject* o = vm->c_data->begin()[index];
504504+505505+ return is_type(o, vm->tp_str);
506506+}
507507+bool pkpy_is_voidp(pkpy_vm* vm_handle, int index) {
508508+ CVM* vm = (CVM*) vm_handle;
509509+ index = lua_to_cstack_index(index, vm->c_data->size());
510510+ PyObject* o = vm->c_data->begin()[index];
511511+512512+ return is_type(o, VoidP::_type(vm));
513513+}
514514+515515+bool pkpy_is_none(pkpy_vm* vm_handle, int index) {
516516+ CVM* vm = (CVM*) vm_handle;
517517+ index = lua_to_cstack_index(index, vm->c_data->size());
518518+ PyObject* o = vm->c_data->begin()[index];
519519+520520+ return o == vm->None;
521521+}
522522+523523+bool pkpy_check_global(pkpy_vm* vm_handle, const char* name) {
524524+ CVM* vm = (CVM*) vm_handle;
525525+ SAFEGUARD_OPEN
526526+ PyObject* o = vm->_main->attr().try_get(name);
527527+ if (o == nullptr) {
528528+ o = vm->builtins->attr().try_get(name);
529529+ if (o == nullptr)
530530+ return false;
531531+ }
532532+ return true;
533533+534534+ SAFEGUARD_CLOSE
535535+}
536536+537537+bool pkpy_check_error(pkpy_vm* vm_handle) {
538538+ CVM* vm = (CVM*) vm_handle;
539539+ SAFEGUARD_OPEN
540540+ if (vm->c_data->size() > 0 && vm->c_data->top() == nullptr)
541541+ return true;
542542+ return false;
543543+ SAFEGUARD_CLOSE
544544+}
545545+546546+547547+bool pkpy_check_stack(pkpy_vm* vm_handle, int free) {
548548+ CVM* vm = (CVM*) vm_handle;
549549+ return free + vm->c_data->size() <= PKPY_STACK_SIZE;
550550+}
551551+552552+int pkpy_stack_size(pkpy_vm* vm_handle) {
553553+ CVM* vm = (CVM*) vm_handle;
554554+ return vm->c_data->size();
555555+}
556556+557557+bool pkpy_pop(pkpy_vm* vm_handle, int n) {
558558+ CVM* vm = (CVM*) vm_handle;
559559+ vm->c_data->shrink(n);
560560+ return true;
561561+}
562562+563563+564564+bool pkpy_push(pkpy_vm* vm_handle, int index) {
565565+ CVM* vm = (CVM*) vm_handle;
566566+ index = lua_to_cstack_index(index, vm->c_data->size());
567567+ vm->c_data->push(vm->c_data->begin()[index]);
568568+ return true;
569569+}
570570+571571+572572+bool pkpy_error(pkpy_vm* vm_handle, const char* message) {
573573+ CVM* vm = (CVM*) vm_handle;
574574+ ERRHANDLER_OPEN
575575+ throw Exception("CBindingError", message);
576576+ ERRHANDLER_CLOSE
577577+}
578578+
+115
vendor/pocketpy/pocketpy_c.h
···11+#ifndef POCKETPY_C_H
22+#define POCKETPY_C_H
33+44+#ifdef __cplusplus
55+extern "C" {
66+#endif
77+88+#include <stdbool.h>
99+#include <stdint.h>
1010+1111+typedef struct pkpy_vm_handle pkpy_vm;
1212+1313+//we we take a lot of inspiration from the lua api for these bindings
1414+//the key difference being most methods return a bool,
1515+//true if it succeeded false if it did not
1616+1717+//if a method returns false call the pkpy_clear_error method to check the error and clear it
1818+//if pkpy_clear_error returns false it means that no error was set, and it takes no action
1919+//if pkpy_clear_error returns true it means there was an error and it was cleared,
2020+//it will provide a string summary of the error in the message parameter (if it is not NULL)
2121+//if null is passed in as message, and it will just print the message to stderr
2222+bool pkpy_clear_error(pkpy_vm*, char** message);
2323+//NOTE you are responsible for freeing message
2424+2525+//this will cause the vm to enter an error state and report the given message
2626+//when queried
2727+//note that at the moment this is more like a panic than throwing an error
2828+//the user will not be able to catch it with python code
2929+bool pkpy_error(pkpy_vm*, const char* message);
3030+3131+3232+pkpy_vm* pkpy_vm_create(bool use_stdio, bool enable_os);
3333+bool pkpy_vm_run(pkpy_vm*, const char* source);
3434+void pkpy_vm_destroy(pkpy_vm*);
3535+3636+typedef int (*pkpy_function)(pkpy_vm*);
3737+3838+bool pkpy_pop(pkpy_vm*, int n);
3939+4040+//push the item at index onto the top of the stack (as well as leaving it where
4141+//it is on the stack)
4242+bool pkpy_push(pkpy_vm*, int index);
4343+4444+bool pkpy_push_function(pkpy_vm*, pkpy_function);
4545+bool pkpy_push_int(pkpy_vm*, int);
4646+bool pkpy_push_float(pkpy_vm*, double);
4747+bool pkpy_push_bool(pkpy_vm*, bool);
4848+bool pkpy_push_string(pkpy_vm*, const char*);
4949+bool pkpy_push_stringn(pkpy_vm*, const char*, int length);
5050+bool pkpy_push_voidp(pkpy_vm*, void*);
5151+bool pkpy_push_none(pkpy_vm*);
5252+5353+bool pkpy_set_global(pkpy_vm*, const char* name);
5454+bool pkpy_get_global(pkpy_vm*, const char* name);
5555+5656+//first push callable you want to call
5757+//then push the arguments to send
5858+//argc is the number of arguments that was pushed (not counting the callable)
5959+bool pkpy_call(pkpy_vm*, int argc);
6060+6161+//first push the object the method belongs to (self)
6262+//then push the the argments
6363+//argc is the number of arguments that was pushed (not counting the callable or self)
6464+//name is the name of the method to call on the object
6565+bool pkpy_call_method(pkpy_vm*, const char* name, int argc);
6666+6767+6868+//we will break with the lua api here
6969+//lua uses 1 as the index to the first pushed element for all of these functions
7070+//but we will start counting at zero to match python
7171+//we will allow negative numbers to count backwards from the top
7272+bool pkpy_to_int(pkpy_vm*, int index, int* ret);
7373+bool pkpy_to_float(pkpy_vm*, int index, double* ret);
7474+bool pkpy_to_bool(pkpy_vm*, int index, bool* ret);
7575+bool pkpy_to_voidp(pkpy_vm*, int index, void** ret);
7676+7777+//this method provides a strong reference, you are responsible for freeing the
7878+//string when you are done with it
7979+bool pkpy_to_string(pkpy_vm*, int index, char** ret);
8080+8181+//this method provides a weak reference, it is only valid until the
8282+//next api call
8383+//it is not null terminated
8484+bool pkpy_to_stringn(pkpy_vm*, int index, const char** ret, int* size);
8585+8686+8787+//these do not follow the same error semantics as above, their return values
8888+//just say whether the check succeeded or not, or else return the value asked for
8989+9090+bool pkpy_is_int(pkpy_vm*, int index);
9191+bool pkpy_is_float(pkpy_vm*, int index);
9292+bool pkpy_is_bool(pkpy_vm*, int index);
9393+bool pkpy_is_string(pkpy_vm*, int index);
9494+bool pkpy_is_voidp(pkpy_vm*, int index);
9595+bool pkpy_is_none(pkpy_vm*, int index);
9696+9797+9898+//will return true if global exists
9999+bool pkpy_check_global(pkpy_vm*, const char* name);
100100+101101+//will return true if the vm is currently in an error state
102102+bool pkpy_check_error(pkpy_vm*);
103103+104104+//will return true if at least free empty slots remain on the stack
105105+bool pkpy_check_stack(pkpy_vm*, int free);
106106+107107+//returns the number of elements on the stack
108108+int pkpy_stack_size(pkpy_vm*);
109109+110110+111111+#ifdef __cplusplus
112112+}
113113+#endif
114114+115115+#endif