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: http://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)