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
Website: http://sourceware.org/libffi/
Platforms supported: Windows, Linux, DOS
Headers to include: ffi.bi
Header version: 3.1
Example
Hello world:
Closures:
#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
' 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)
' 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)