Feat: Expose caller information to foreign functions#1215
Conversation
|
Hi,
Please provide comparative benchmarks.
I'm surprised it does not break meta tests, but maybe I'm mixing things.
But more importantly, since there is no stack introspection in the API, how
does it do what you claim it allows?
|
|
I’m surprised and glad to see someone respond 🙂 My intention is to provide a convenient way to use libFFI in my app. I was experimenting with something like this: foreign class Raylib is FFI {
#!extern(dll="raylib", args="int,int,char*")
foreign static InitWindow(width, height, title)
#!extern(dll="raylib")
foreign static BeginDrawing()
#!extern(dll="raylib")
foreign static EndDrawing()
#!extern(dll="raylib")
foreign static WindowShouldClose()
#!extern(dll="raylib")
foreign static CloseWindow()
}My first attempt was to parse these attributes at bind time, but I discovered that the compiler does not emit class attributes until The next approach I tried was parsing the attributes at runtime. I bind all foreign methods that extend the void executeFunctionFn(WrenVM *vm) {
// ...
// get the current frame
CallFrame* frame = &vm->fiber->frames[vm->fiber->numFrames - 1];
ObjFn* fn = frame->closure->fn;
uint16_t methodSymbol =
(uint16_t)((*(frame->ip - 2) << 8) | *(frame->ip - 1));
fprintf(stderr, "Method symbol: %d\n", methodSymbol);
// Get the actual method name from the VM using the symbol
if (targetClass != NULL) {
methodName = vm->methodNames.data[methodSymbol]->value;
}
fprintf(stderr,
"Executing foreign method %s.%s.%s\n",
moduleName, className, methodName);
// ...
}This produces output like: I’ll get back with a benchmark later, it’s only been a day since I started working with the codebase, and I’m still getting familiar with it. I’m also not sure whether it’s intentional that |
|
It may be possible to be able to do lazy evaluation of external symbols
that way.
There are probably some other place to hack and a more thought attribute
convention, to do it more "cleanly". There are quite some considerations
behind it to consider, like supporting possible other VM implemtations.
Providing a binding generator was considered the way in the past, to
guarantee the symbols presence, but do we really need that guarantee.
Even if ffi as this is not the way, lazy loading of external symbols can be
an interesting feature to have.
|
This change enhances the foreign function interface by allowing foreign functions to inspect their call site within the Wren VM.
By saving the VM's state with
STORE_FRAME()before a foreign call, the foreign function can now access the caller's context, including the instruction pointer. This allows for runtime reflection, such as determining the method name that was used to invoke the foreign function by inspecting the bytecode.This enables more advanced use cases for foreign functions that require information about their invocation context. The
LOAD_FRAME()macro ensures that the VM state is correctly restored after the foreign function returns, maintaining the integrity of the interpreter.Also, it breaks no test.