LibFFI — это библиотека интерфейса внешних функций, позволяющая произвольно
вызывать собственную функцию без указателей и связывать указатели функции
для универсальных функций, которые принимают переменные аргументы. Она
используется для привязки нативного кода в современных скриптовых языках.
Вебсайт: http://sourceware.org/libffi/
Поддерживаемые платформы: Windows, Linux, DOS
Заголовки: ffi.bi
Версия заголовков: 3.0.10
Примеры
Hello world:
#include "ffi.bi"
' Простой эквивалент функции "puts"
Function printer cdecl (ByVal s As ZString Ptr) As Integer
Print *s
Return 42
End Function
' Инициализация аргументов информации векторов
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}
' Инициализация cif
Dim cif As ffi_cif
Dim result As ffi_status
result = ffi_prep_cif( _
@cif, _ ' вызов
объекта интерфейса
FFI_DEFAULT_ABI, _ ' двоичный
тип интерфейса
1, _ ' количество
аргументов
@ffi_type_uint, _ ' возвращаемый
тип
@args(0) _ ' аргументы
)
' Вызов функции
Dim return_value As Integer
If result = FFI_OK Then
s = @"Hello world"
ffi_call(@cif, FFI_FN(@printer), @return_value, @values(0))
'Значения содержат указатель на arg
функции, так, что для того, чтобы
'Вызвать puts() еще раз, нужно только
изменить
'Значение 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"
' Действует как puts с файлом во время вложения.
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
' Выделение памяти для closure и функции
связи
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
' Инициализация
аргументов информации вектора
Dim args(0 To 0) As ffi_type Ptr = {@ffi_type_pointer}
' Инициализация
интерфейса вызова
Dim cif As ffi_cif
Dim prep_result As ffi_status = ffi_prep_cif( _
@cif, _ ' вызов
объекта интерфейса
FFI_DEFAULT_ABI, _ ' двоичный
тип интерфейса
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, _ ' актуальная
функция closure
@ConsoleFile, _ ' пользовательские
данные, нашего консольного файла #
PrinterBinding _ ' указатель
для связи
)
If prep_result = FFI_OK Then
' Вызов
связи как натуральный вызов функции
Dim Result As Integer
Result = PrinterBinding("Hello World!")
Print Using "Returned &"; Result
End If
Close ConsoleFile
End If
End If
' Очистка
ffi_closure_free(closure)