Help Center
Help CenterFreeBASICTutorials

libffi

Documentation

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)