As a short proof of concept started in on nekoffi. Integrating NekoVM with libffi.
This example doesn’t gain much over the normal NekoVM builtin C FFI, but pass 2 will include dynamic symbol lookup, which should mean a single $loader.loadprim per Neko source to get at just about any and all C library functions.
The tl;dr; Using NekoVM C-FFI integrated with libffi will mean Neko programmers will not have to write any C wrappers to allow primitive access to C functions.
What follows is baby step 1, to make sure things don’t jump and catch fire.
nekoffi.c
/*
Author: Brian Tiffin
Dedicated to the public domain
Date started: October 2018
Modified: 2018-10-23/22:30-0400 btiffin
Tectonics:
gcc -shared -fPIC -o nekoffi.ndll nekoffi.c -lffi
*/
/* NekoVM with libffi */
#include <stdio.h>
#include <neko.h>
#include <ffi.h>
value
ffi(value message)
{
ffi_cif cif;
ffi_type *args[1];
void *values[1];
char *s;
ffi_arg rc;
args[0] = &ffi_type_pointer;
values[0] = &s;
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_sint, args) == FFI_OK) {
s = val_string(message);
ffi_call(&cif, puts, &rc, values);
}
return alloc_int(rc);
}
DEFINE_PRIM(ffi, 1);
nekoffi.neko
/**
libffi integration with Neko
*/
var ffi = $loader.loadprim("nekoffi@ffi", 1);
ffi("Hello, ffi");
ffi("Hello, again ffi");
(GNU) make rules:
.RECIPEPREFIX = >
# NekoVM with libffi
nekoffi.ndll: nekoffi.c
> gcc -shared -fPIC -o nekoffi.ndll nekoffi.c -lffi
nekoffi: nekoffi.neko
> nekoc nekoffi.neko
> nekotools boot nekoffi.n
And a sample run:
prompt$ make nekoffi
gcc -w -shared -fPIC -o nekoffi.ndll nekoffi.c -lffi
nekoc nekoffi.neko
nekotools boot nekoffi.n
prompt$ ./nekoffi
Hello, ffi
Hello, again ffi
Calling puts via libffi from a Neko string.
Note: Don’t do this at home (just yet). -w turns off a warning about incompatible pointer types which is just noise for the phase 1 trial (but will be fixed in phase 2).
Anyway, it works. So on to step 2.
In the trial, puts is hardcoded. That will change on phase 2 to a Neko interface of
ffi("C-Function", RETURN-TYPE, args...)
LoadLibrary/dlopen dlsym will be used to get the actual function pointer for use with libffi in the next cut.
Similar to the design used with uniffi, a Unicon version of a similar code sequence, there are wrinkles to overcome. The types may require overrides. Neko float values (which are C double), might need to be cast to an actual C float type. Neko int may need to be cast to C short, etc. Instead of requiring each and every argument of an ffi call to be explicitly typed, a simple pair can be passed with an override type when required. I hope, not there yet, but it’ll be a design goal.
libffi or GitHub - libffi/libffi: A portable foreign-function interface library.
For a more complete view on how this might shake out if step 2 succeeds see: Multilanguage — Unicon Programming v0.6.148
Have good, make well