From 30bb620dba83d9be32db8a0fdf751a800f9a2376 Mon Sep 17 00:00:00 2001 From: Brandon Dyck Date: Sat, 26 Nov 2022 21:45:16 -0700 Subject: [PATCH] Wrapped ph7_create_function --- cgo.c | 4 ++++ cgo.h | 3 +++ ph7.go | 38 +++++++++++++++++++++++++++++++++++++- 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/cgo.c b/cgo.c index d50841e..03d1175 100644 --- a/cgo.c +++ b/cgo.c @@ -11,3 +11,7 @@ int vm_extract_output(ph7_vm *pVm, const char **pzPtr, int *pLen) { int vm_set_output_callback(ph7_vm *pVm, void *pUserData) { return ph7_vm_config(pVm, PH7_VM_CONFIG_OUTPUT, &write_vm_output, pUserData); } + +int vm_create_function(ph7_vm *pVm, const char *zName, void *pUserData) { + return ph7_create_function(pVm, zName, call_foreign_function, pUserData); +} diff --git a/cgo.h b/cgo.h index cf529a7..c8576ab 100644 --- a/cgo.h +++ b/cgo.h @@ -6,3 +6,6 @@ int vm_extract_output(ph7_vm *pVm, const char **pzPtr, int *pLen); extern int write_vm_output(void*, unsigned int, void*); int vm_set_output_callback(ph7_vm *pVm, void *pUserData); + +extern int call_foreign_function(ph7_context *pCtx, int argc, ph7_value **argv); +int vm_create_function(ph7_vm *pVm, const char *zName, void *pUserData); diff --git a/ph7.go b/ph7.go index 2239e9d..113f3e3 100644 --- a/ph7.go +++ b/ph7.go @@ -53,6 +53,8 @@ type Error struct { Code ResultCode } +// TODO create a CompileError that contains the error log text + func newError(code C.int) error { if code != C.PH7_OK { return Error{ @@ -112,12 +114,17 @@ func (e Engine) Close() error { return newError(C.ph7_release(e.ptr)) } +type Value C.ph7_value + +type Context C.ph7_context + type VM struct { ptr *C.ph7_vm pointerKey unsafe.Pointer outputWriter io.Writer // TODO clear outputWriteError when resetting VM - outputWriteErr error + outputWriteErr error + userFunctionKeys []unsafe.Pointer } func newVM(cvm *C.ph7_vm) *VM { @@ -170,5 +177,34 @@ func (vm *VM) Reset() error { func (vm *VM) Close() error { pointer.Unref(vm.pointerKey) + for _, key := range vm.userFunctionKeys { + pointer.Unref(key) + } return newError(C.ph7_vm_release(vm.ptr)) } + +type ForeignFunction interface { + Call(ctx *Context, args []*Value) ResultCode +} + +//export call_foreign_function +func call_foreign_function(ctx *C.ph7_context, argc C.int, argv **C.ph7_value) C.int { + fkey := C.ph7_context_user_data(ctx) + f := pointer.Restore(fkey).(ForeignFunction) + args := make([]*Value, 0, argc) + argvSlice := unsafe.Slice(argv, argc) + for i := range argvSlice { + args = append(args, (*Value)(argvSlice[i])) + } + return C.int(f.Call((*Context)(ctx), args)) +} + +func (vm *VM) CreateFunction(name string, f ForeignFunction) error { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + + fkey := pointer.Save(f) + vm.userFunctionKeys = append(vm.userFunctionKeys, fkey) + + return newError(C.vm_create_function(vm.ptr, cname, fkey)) +}