I am currently looking into implementing a cleaner way to call native C functions from the Gravity scripting language.
So far, the most simplistic example would be this one:
int add(int lhs, int rhs) {
return lhs + rhs;
}
static void gravity_wrap_add(
gravity_vm* vm,
gravity_value_t* args, uint32_t nargs,
uint32_t retIndex, void* data
) {
int lhs, rhs, rt;
// Unwrap
lhs = VALUE_AS_INT(args[1]);
rhs = VALUE_AS_INT(args[2]);
// Perform call, capture return
rt = add(lhs, rhs);
// Forward the return
gravity_vm_setslot(vm, VALUE_FROM_INT(rt), retIndex);
}
By using C++ (98) templating or C preprocessor magic, would there be a way to generate wrapper functions?
A very, very crunched example of the above wrapper function, would be this one:
static void gravity_wrap_add(
gravity_vm* vm,
gravity_value_t* args, uint32_t nargs,
uint32_t retIndex, void* data
) {
gravity_vm_setslot(vm,
VALUE_FROM_INT(
add(VALUE_AS_INT(args[1]), VALUE_AS_INT(args[2]))
),
retIndex);
}
This version is technically what I want to achieve - but through methods like the preprocessor or C++ templating. For cross-platform compatibility reasons, I'd like to stick with C++98 (since MSVC isn't exactly good on modern features).
It’s pretty tedious without variadic templates, but you should be able to do a small number of arguments:
As usual,
voidreturn types will be a pain; you have to repeat each argument-count overload forRofvoid.It would be possible to use deduction to avoid repeating the signature when using
wrap, but then you get fewer functions and extra closure objects to distinguish them (which you can presumably use via thedataargument).