Files
wren/test/api/foreign_class.c
Bob Nystrom ed6fad6153 Get rid of fiber for finalizers.
Instead, finalizers just get access to the foreign object's raw bytes.
This is deliberately limiting, since it discourages the user from
interacting with the VM in the middle of a GC.
2015-12-28 08:06:29 -08:00

118 lines
2.7 KiB
C

#include <stdio.h>
#include <string.h>
#include "foreign_class.h"
static int finalized = 0;
static void apiFinalized(WrenVM* vm)
{
wrenSetSlotDouble(vm, 0, finalized);
}
static void counterAllocate(WrenVM* vm)
{
double* value = (double*)wrenAllocateForeign(vm, sizeof(double));
*value = 0;
}
static void counterIncrement(WrenVM* vm)
{
double* value = (double*)wrenGetSlotForeign(vm, 0);
double increment = wrenGetSlotDouble(vm, 1);
*value += increment;
}
static void counterValue(WrenVM* vm)
{
double value = *(double*)wrenGetSlotForeign(vm, 0);
wrenSetSlotDouble(vm, 0, value);
}
static void pointAllocate(WrenVM* vm)
{
double* coordinates = (double*)wrenAllocateForeign(vm, sizeof(double[3]));
// This gets called by both constructors, so sniff the slot count to see
// which one was invoked.
if (wrenGetSlotCount(vm) == 1)
{
coordinates[0] = 0.0;
coordinates[1] = 0.0;
coordinates[2] = 0.0;
}
else
{
coordinates[0] = wrenGetSlotDouble(vm, 1);
coordinates[1] = wrenGetSlotDouble(vm, 2);
coordinates[2] = wrenGetSlotDouble(vm, 3);
}
}
static void pointTranslate(WrenVM* vm)
{
double* coordinates = (double*)wrenGetSlotForeign(vm, 0);
coordinates[0] += wrenGetSlotDouble(vm, 1);
coordinates[1] += wrenGetSlotDouble(vm, 2);
coordinates[2] += wrenGetSlotDouble(vm, 3);
}
static void pointToString(WrenVM* vm)
{
double* coordinates = (double*)wrenGetSlotForeign(vm, 0);
char result[100];
sprintf(result, "(%g, %g, %g)",
coordinates[0], coordinates[1], coordinates[2]);
wrenSetSlotString(vm, 0, result);
}
static void resourceAllocate(WrenVM* vm)
{
int* value = (int*)wrenAllocateForeign(vm, sizeof(int));
*value = 123;
}
static void resourceFinalize(void* data)
{
// Make sure we get the right data back.
int* value = (int*)data;
if (*value != 123) exit(1);
finalized++;
}
WrenForeignMethodFn foreignClassBindMethod(const char* signature)
{
if (strcmp(signature, "static ForeignClass.finalized") == 0) return apiFinalized;
if (strcmp(signature, "Counter.increment(_)") == 0) return counterIncrement;
if (strcmp(signature, "Counter.value") == 0) return counterValue;
if (strcmp(signature, "Point.translate(_,_,_)") == 0) return pointTranslate;
if (strcmp(signature, "Point.toString") == 0) return pointToString;
return NULL;
}
void foreignClassBindClass(
const char* className, WrenForeignClassMethods* methods)
{
if (strcmp(className, "Counter") == 0)
{
methods->allocate = counterAllocate;
return;
}
if (strcmp(className, "Point") == 0)
{
methods->allocate = pointAllocate;
return;
}
if (strcmp(className, "Resource") == 0)
{
methods->allocate = resourceAllocate;
methods->finalize = resourceFinalize;
return;
}
}