libffi

LibFFI is a foreign function interface library allowing programs to 
arbitrarily call native function without pointers and to bind function 
pointers to generic functions which take variable arguments via closures. 
It is used to bind native code in modern scripting languages.

Website: https://sourceware.org/libffi/
Platforms supported: Windows, Linux, DOS
Headers to include: ffi.bi
Header version: 3.1

Example
   Hello world:
   #include "ffi.bi"

   ' Simple "puts" equivalent function
   Function printer cdecl (ByVal s As ZString Ptr) As Integer
      Print *s
      Return 42
   End Function

   ' Initialize the argument info vectors
   Dim s As ZString Ptr
   Dim args(0 To 0) As ffi_type Ptr = {@ffi_type_pointer}
   Dim values(0 To 0) As Any Ptr = {@s}

   ' Initialize the cif
   Dim cif As ffi_cif
   Dim result As ffi_status
   result = ffi_prep_cif( _
      @cif,              _ ' call interface object
      FFI_DEFAULT_ABI,   _ ' binary interface type
      1,                 _ ' number of arguments
      @ffi_type_uint,    _ ' return type
      @args(0)           _ ' arguments
   )

   ' Call function
   Dim return_value As Integer
   If result = FFI_OK Then
      s = @"Hello world"
      ffi_call(@cif, FFI_FN(@printer), @return_value, @values(0))

      ' values holds a pointer to the function's arg, so to
      ' call puts() again all we need to do is change the
      ' value of s */
      s = @"This is cool!"
      ffi_call(@cif, FFI_FN(@printer), @return_value, @values(0))
      Print Using "Function returned &"; return_value
   End If

   Closures:
   #include "ffi.bi"

   ' Acts like puts with the file given at time of enclosure. 
   Sub Printer cdecl(ByVal cif As ffi_cif Ptr, ByVal ret As Any Ptr, ByVal args As Any Ptr Ptr, ByVal File As Any Ptr)
      Write #*CPtr(Integer Ptr, file), **CPtr(ZString Ptr Ptr, args[0])
      *CPtr(UInteger Ptr, ret) = 42
   End Sub

   ' Allocate the closure and function binding
   Dim PrinterBinding As Function(ByVal s As ZString Ptr) As Integer
   Dim closure As ffi_closure Ptr 
   closure = ffi_closure_alloc(SizeOf(ffi_closure), @PrinterBinding)

   If closure <> 0 Then
      ' Initialize the argument info vector
      Dim args(0 To 0) As ffi_type Ptr = {@ffi_type_pointer}
      
      ' Initialize the call interface
      Dim cif As ffi_cif
      Dim prep_result As ffi_status = ffi_prep_cif( _
         @cif,            _ ' call interface object
         FFI_DEFAULT_ABI, _ ' binary interface type
         1,               _ ' number of arguments
         @ffi_type_uint,  _ ' return type
         @args(0)         _ ' arguments
      ) 
      If prep_result = FFI_OK Then
         ' Open console file to send to PrinterBinding as user data
         Dim ConsoleFile As Integer = FreeFile()
         Open Cons For Output As ConsoleFile
         
         ' Initialize the closure, setting user data to the console file
         prep_result = ffi_prep_closure_loc( _
            closure,         _ ' closure object
            @cif,            _ ' call interface object
            @Printer,        _ ' actual closure function
            @ConsoleFile,    _ ' user data, our console file #
            PrinterBinding   _ ' pointer to binding
         )
         If prep_result = FFI_OK Then
            ' Call binding as a natural function call
            Dim Result As Integer
            Result = PrinterBinding("Hello World!")
            Print Using "Returned &"; Result
         End If
         
         Close ConsoleFile
      End If
   End If

   ' Clean up
   ffi_closure_free(closure)

