foreign_struct(Name, Elements) :-
'$define_foreign_struct'(Name, Elements).
+
+%% use_foreign_module(+LibName, +Predicates)
+%
+% - LibName the path to the shared library to load/bind
+% - Predicates list of function definitions
+%
+% Each function definition is a functor of arity 2.
+% The functor name is the name of the function to bind,
+% the first argument is the list of arguments of the function,
+% the second argument is the return type of the function.
+%
+% This will define a predicate in the ffi module with the defined name,
+% for void and bool return type functions the arity will match the length of the arguments list,
+% for other return types there will be an additional out parameter.
+%
use_foreign_module(LibName, Predicates) :-
'$load_foreign_lib'(LibName, Predicates),
maplist(assert_predicate, Predicates).
Predicate = (Head:-Body),
assertz(ffi:Predicate).
-
+%% allocate(+Allocator, +Type, +Args, -Ptr)
+%
+% Using the Allocator allocate Type initialized with Args and
+% unify Ptr with a pointer to that allocation.
+%
allocate(Allocator, Type, Args, Ptr) :-
must_be(var, Ptr),
must_be(atom, Type),
must_be(atom, Allocator),
'$ffi_allocate'(Allocator, Type, Args, Ptr).
+
+%% read_ptr(+Type, +Ptr, -Value)
+%
+% Read a value of Type from the pointer Ptr and unify the read value with Value
+%
+% For type cstr take read a nul-terminated utf-8 string starting at Ptr.
+%
read_ptr(Type, Ptr, Value) :-
must_be(var, Value),
must_be(atom, Type),
must_be(integer, Ptr),
'$ffi_read_ptr'(Type, Ptr, Value).
+%% deallocate(+Allocator, +Type, +Ptr)
+%
+% Deallocate the allocation at Ptr of Type allocated with Allocator
+%
deallocate(Allocator, Type, Ptr) :-
must_be(atom, Allocator),
must_be(integer, Ptr),
:- dynamic(is_array_type_defined/1).
+%% array_type(+ElemType, +Len, -ArrayType)
+%
+% unify the ffi type for an array of lenth Len with element type ElemType with ArrayType
+%
array_type(ElemType, Len, ArrayType) :-
(Len =< 0 -> domain_error(greater_than_zero, Len, array_type/3); true),
phrase(format_("$[~a;~d]", [ElemType, Len]), ArrayTypeName),
assertz(is_array_type_defined(ArrayType))
).
+%% with_locals(+Locals, :Goal)
+%
+% Allocate the Locals, evaluate the Goal and deallocate the Locals.
+% The Locals will also be cleandup when Goal fails or throws an error.
+%
+% Locals is a list of local variable definitions let(-Ptr, +Type, +Args).
+% Ptr will be unified with the pointer to the local of Type initialized with Args.
+%
with_locals(Locals, Goal) :-
verify_locals(Locals),
setup_call_cleanup(