From 6bdc8fd4947a0a6c6937f4a00ae1d73c43b74d5e Mon Sep 17 00:00:00 2001 From: Kolten Pearson Date: Sat, 29 Apr 2023 13:33:51 -0600 Subject: [PATCH] basic stack based api for creating a binding from c to python is functional --- c_bindings/main.c | 13 +++++++++++++ c_bindings/pocketpy_c.cpp | 24 ++++++++++++++++++++++++ c_bindings/pocketpy_c.h | 14 ++++++++++++++ src/obj.h | 12 +++++++++++- src/vm.h | 21 +++++++++++++++++++-- 5 files changed, 81 insertions(+), 3 deletions(-) diff --git a/c_bindings/main.c b/c_bindings/main.c index 04290ebf..f3592583 100644 --- a/c_bindings/main.c +++ b/c_bindings/main.c @@ -1,12 +1,25 @@ #include "pocketpy_c.h" +void test_binding(pkpy_vm vm) { + pkpy_push_int(vm, 12); +} + int main(int argc, char** argv) { pkpy_vm vm = pkpy_vm_create(true, true); pkpy_vm_exec(vm, "print('hello world!')"); + pkpy_push_int(vm, 11); + pkpy_set_global(vm, "eleven"); + + pkpy_push_cfunction(vm, test_binding); + pkpy_set_global(vm, "binding"); + + pkpy_vm_exec(vm, "print(eleven)"); + pkpy_vm_exec(vm, "print(binding())"); + pkpy_vm_destroy(vm); return 0; diff --git a/c_bindings/pocketpy_c.cpp b/c_bindings/pocketpy_c.cpp index 152ea532..070dfaca 100644 --- a/c_bindings/pocketpy_c.cpp +++ b/c_bindings/pocketpy_c.cpp @@ -19,3 +19,27 @@ void pkpy_vm_destroy(pkpy_vm vm_handle) { delete vm; } +void pkpy_push_cfunction(pkpy_vm vm_handle, pkpy_cfunction f) { + pkpy::VM* vm = (pkpy::VM*) vm_handle; + vm->s_data.push(pkpy::py_var(vm, pkpy::StackFunc((pkpy::StackFuncC) f))); +} + +void pkpy_push_int(pkpy_vm vm_handle, int64_t value) { + pkpy::VM* vm = (pkpy::VM*) vm_handle; + vm->s_data.push(VAR(value)); +} + +void pkpy_push_float(pkpy_vm vm_handle, double value) { + pkpy::VM* vm = (pkpy::VM*) vm_handle; + vm->s_data.push(VAR(value)); +} + +void pkpy_set_global(pkpy_vm vm_handle, const char* name) { + pkpy::VM* vm = (pkpy::VM*) vm_handle; + + vm->_main->attr().set(name, vm->s_data.top()); + + vm->s_data.pop(); +} + + diff --git a/c_bindings/pocketpy_c.h b/c_bindings/pocketpy_c.h index 12672495..80f153cc 100644 --- a/c_bindings/pocketpy_c.h +++ b/c_bindings/pocketpy_c.h @@ -6,6 +6,7 @@ extern "C" { #endif #include +#include typedef struct pkpy_vm_handle* pkpy_vm; @@ -13,6 +14,19 @@ pkpy_vm pkpy_vm_create(bool use_stdio, bool enable_os); void pkpy_vm_exec(pkpy_vm vm_handle, const char* source); void pkpy_vm_destroy(pkpy_vm vm); +////////binding a c function to pocketpy +typedef void (*pkpy_cfunction)(pkpy_vm); + +void pkpy_push_cfunction(pkpy_vm, pkpy_cfunction); +void pkpy_push_int(pkpy_vm, int64_t); +void pkpy_push_float(pkpy_vm, double); + +void pkpy_set_global(pkpy_vm, const char* name); + + + + + #ifdef __cplusplus } #endif diff --git a/src/obj.h b/src/obj.h index 515fcf73..b817c9ee 100644 --- a/src/obj.h +++ b/src/obj.h @@ -23,6 +23,16 @@ struct NativeFunc { PyObject* operator()(VM* vm, ArgsView args) const; }; + +typedef void (*StackFuncC)(VM*); +struct StackFunc { + StackFuncC f; + + StackFunc(StackFuncC f) : f(f) {} + void operator()(VM* vm) const; +}; + + struct FuncDecl { struct KwArg { int key; // index in co->varnames @@ -259,4 +269,4 @@ __T _py_cast(VM* vm, PyObject* obj) { #define CAST(T, x) py_cast(vm, x) #define _CAST(T, x) _py_cast(vm, x) -} // namespace pkpy \ No newline at end of file +} // namespace pkpy diff --git a/src/vm.h b/src/vm.h index b360d941..9ca31153 100644 --- a/src/vm.h +++ b/src/vm.h @@ -100,7 +100,7 @@ public: // for quick access Type tp_object, tp_type, tp_int, tp_float, tp_bool, tp_str; Type tp_list, tp_tuple; - Type tp_function, tp_native_func, tp_iterator, tp_bound_method; + Type tp_function, tp_stack_func, tp_native_func, tp_iterator, tp_bound_method; Type tp_slice, tp_range, tp_module; Type tp_super, tp_exception, tp_bytes, tp_mappingproxy; @@ -414,6 +414,11 @@ inline PyObject* NativeFunc::operator()(VM* vm, ArgsView args) const{ return f(vm, args); } +inline void StackFunc::operator()(VM* vm) const{ + return f(vm); +} + + inline void CodeObject::optimize(VM* vm){ // uint32_t base_n = (uint32_t)(names.size() / kLocalsLoadFactor + 0.5); // perfect_locals_capacity = std::max(find_next_capacity(base_n), NameDict::__Capacity); @@ -425,6 +430,7 @@ DEF_NATIVE_2(List, tp_list) DEF_NATIVE_2(Tuple, tp_tuple) DEF_NATIVE_2(Function, tp_function) DEF_NATIVE_2(NativeFunc, tp_native_func) +DEF_NATIVE_2(StackFunc, tp_stack_func) DEF_NATIVE_2(BoundMethod, tp_bound_method) DEF_NATIVE_2(Range, tp_range) DEF_NATIVE_2(Slice, tp_slice) @@ -927,6 +933,17 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){ // [unbound, self, args..., kwargs...] } + if(is_non_tagged_type(callable, tp_stack_func)) { + const auto& f = OBJ_GET(StackFunc, callable); + if(ARGC != 0) TypeError("stack_func does not track argument counts "); + if(KWARGC != 0) TypeError("stack_func does not accept keyword arguments"); + f(this); + PyObject* ret = s_data.top(); + s_data.reset(p0); + return ret; + } + + ArgsView args(p1 - ARGC - int(method_call), p1); if(is_non_tagged_type(callable, tp_native_func)){ @@ -1201,4 +1218,4 @@ inline Str obj_type_name(VM *vm, Type type){ #undef PY_VAR_INT #undef PY_VAR_FLOAT -} // namespace pkpy \ No newline at end of file +} // namespace pkpy