forked from Mirror/wren
131 lines
3.0 KiB
C
131 lines
3.0 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*)wrenSetSlotNewForeign(vm, 0, 0, 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*)wrenSetSlotNewForeign(vm, 0, 0, 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*)wrenSetSlotNewForeign(vm, 0, 0, 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++;
|
|
}
|
|
|
|
static void badClassAllocate(WrenVM* vm)
|
|
{
|
|
wrenEnsureSlots(vm, 1);
|
|
wrenSetSlotString(vm, 0, "Something went wrong");
|
|
wrenAbortFiber(vm, 0);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
if (strcmp(className, "BadClass") == 0)
|
|
{
|
|
methods->allocate = badClassAllocate;
|
|
return;
|
|
}
|
|
}
|