Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The need for a bindings generator tool #342

Open
luauser32167 opened this issue Feb 6, 2024 · 2 comments
Open

The need for a bindings generator tool #342

luauser32167 opened this issue Feb 6, 2024 · 2 comments
Labels
enhancement New feature or request

Comments

@luauser32167
Copy link
Contributor

Suppose we have the following C library:

mylib.h

#ifndef MYLIB_H
#define MYLIB_H
#include <stdint.h>
int64_t mylib_add(int64_t a, int64_t b);
int64_t mylib_mul(int64_t a, int64_t b);
#endif // MYLIB_H

mylib.c

#include <stdint.h>
#include "mylib.h"
int64_t mylib_add(int64_t a, int64_t b) { return a + b; }
int64_t mylib_mul(int64_t a, int64_t b) { return a * b; }

and we wanted to use it from Umka:
script.um

import "mymod.um"
fn main() {
  printf("10 + 20 = %d\n", mymod.add(10, 20));
  printf("30 * 40 = %d\n", mymod.mul(30, 40));
}

We would need to write the following "glue" code:

// fn mymod.add(a, b: int): int;
static void um_mymod_add(UmkaStackSlot* args, UmkaStackSlot* ret) {
  int64_t a = args[1].intVal;
  int64_t b = args[0].intVal;
  ret->intVal = mylib_add(a, b);
}

// fn mymod.mul(a, b: int): int;
static void um_mymod_mul(UmkaStackSlot* args, UmkaStackSlot* ret) {
  int64_t a = args[1].intVal;
  int64_t b = args[0].intVal;
  ret->intVal = mylib_mul(a, b);
}

char const* mymodName = "mymod.um";
static char const* mymodText =
"fn um_mymod_add(a, b: int) : int;\n"
"fn add*(a, b: int) : int { return um_mymod_add(a, b); }\n"
"\n"
"fn um_mymod_mul(a, b: int) : int;\n"
"fn mul*(a, b: int) : int { return um_mymod_mul(a, b); }\n"
"\n"
;

static void bindingsInit(void* U) {
  umkaAddFunc(U, "um_mymod_add", &um_mymod_add);
  umkaAddFunc(U, "um_mymod_mul", &um_mymod_mul);
}

Having to manually write this "glue code" is annoying because for every function that we want to make available to script.um, we need to make changes to 3 places. The first and most tedious is the wrapper function that reads its arguments from the UmkaStackSlot* args, where the last argument is at index 0, next argument is at index 1, etc and writes its results (if any) to UmkaStackSlot* ret. After writing the wrapper function we need to write a declaration for it in Umka fn um_mymod_add(a, b: int) : int; and also the function that users are going to call that just calls it fn add*(a, b: int) : int { return um_mymod_add(a, b); }. And finally we have to register the function umkaAddFunc(U, "um_mymod_add", &um_mymod_add);.

My proposal is that there should be a tool that generates the "glue code" from header files (mylib.h). It doesn't have to be super robust to be useful, it could just handle a subset of C declarations (struct, enum and function declarations) that can be mapped to Umka.

@vtereshkov vtereshkov added the enhancement New feature or request label Feb 6, 2024
@vtereshkov
Copy link
Owner

I think @RobLoach may already have something like this. He was working on Umka bindings for raylib:

https://github.com/robloach/raylib-umka

@RobLoach
Copy link

RobLoach commented Feb 6, 2024

Thanks. Was a fun project to put together. Umka's binding API made it really easy to integrate with raylib. While I could've likely used Umka to parse raylib.h and output the Umka/C bindings, I am lazy and used JavaScript to build the generator.

I'd be more than happy with moving the generator to be a bit more abstract, or ported to Umka itself. Feel free to make some issues in the queue if you have any ideas.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants