feat: add WrenValue handle API for persistent object references outside VM
Introduce WrenValue type and wrenGetArgumentValue/wrenReleaseValue functions to allow C code to hold GC-safe references to Wren objects across foreign calls. Implement doubly-linked list management in VM struct, mark value handles during garbage collection, and add assertion in wrenFreeVM to detect unreleased values. Update test infrastructure with new get_value test case and rename existing test binding functions to camelCase convention.
This commit is contained in:
@@ -4,6 +4,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// A single virtual machine for executing Wren code.
|
||||
//
|
||||
// Wren has no global state, so all state stored by a running interpreter lives
|
||||
// here.
|
||||
typedef struct WrenVM WrenVM;
|
||||
|
||||
// A handle to a method, bound to a receiver.
|
||||
@@ -11,6 +15,13 @@ typedef struct WrenVM WrenVM;
|
||||
// This is used to call a Wren method on some object from C code.
|
||||
typedef struct WrenMethod WrenMethod;
|
||||
|
||||
// A handle to a Wren object.
|
||||
//
|
||||
// This lets code outside of the VM hold a persistent reference to an object.
|
||||
// After a value is acquired, and until it is released, this ensures the
|
||||
// garbage collector will not reclaim it.
|
||||
typedef struct WrenValue WrenValue;
|
||||
|
||||
// A generic allocation function that handles all explicit memory management
|
||||
// used by Wren. It's used like so:
|
||||
//
|
||||
@@ -169,6 +180,10 @@ void wrenCall(WrenVM* vm, WrenMethod* method, const char* argTypes, ...);
|
||||
// no longer be used.
|
||||
void wrenReleaseMethod(WrenVM* vm, WrenMethod* method);
|
||||
|
||||
// Releases the reference stored in [value]. After calling this, [value] can no
|
||||
// longer be used.
|
||||
void wrenReleaseValue(WrenVM* vm, WrenValue* value);
|
||||
|
||||
// The following functions read one of the arguments passed to a foreign call.
|
||||
// They may only be called while within a function provided to
|
||||
// [wrenDefineMethod] or [wrenDefineStaticMethod] that Wren has invoked.
|
||||
@@ -205,6 +220,12 @@ double wrenGetArgumentDouble(WrenVM* vm, int index);
|
||||
// function returns, since the garbage collector may reclaim it.
|
||||
const char* wrenGetArgumentString(WrenVM* vm, int index);
|
||||
|
||||
// Creates a handle for the value passed as an argument to a foreign call.
|
||||
//
|
||||
// This will prevent the object that is referred to from being garbage collected
|
||||
// until the handle is released by calling [wrenReleaseValue()].
|
||||
WrenValue* wrenGetArgumentValue(WrenVM* vm, int index);
|
||||
|
||||
// The following functions provide the return value for a foreign method back
|
||||
// to Wren. Like above, they may only be called during a foreign call invoked
|
||||
// by Wren.
|
||||
@@ -228,4 +249,10 @@ void wrenReturnDouble(WrenVM* vm, double value);
|
||||
// [text] will be calculated using `strlen()`.
|
||||
void wrenReturnString(WrenVM* vm, const char* text, int length);
|
||||
|
||||
// Provides the return value for a foreign call.
|
||||
//
|
||||
// This uses the value referred to by the handle as the return value, but it
|
||||
// does not release the handle.
|
||||
void wrenReturnValue(WrenVM* vm, WrenValue* value);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user