1/*  Part of SWI-Prolog
    2
    3    Author:        Jan Wielemaker
    4    E-mail:        J.Wielemaker@vu.nl
    5    WWW:           http://www.swi-prolog.org
    6    Copyright (c)  2018-2023, VU University Amsterdam
    7                              SWI-Prolog Solutions b.v.
    8    All rights reserved.
    9
   10    Redistribution and use in source and binary forms, with or without
   11    modification, are permitted provided that the following conditions
   12    are met:
   13
   14    1. Redistributions of source code must retain the above copyright
   15       notice, this list of conditions and the following disclaimer.
   16
   17    2. Redistributions in binary form must reproduce the above copyright
   18       notice, this list of conditions and the following disclaimer in
   19       the documentation and/or other materials provided with the
   20       distribution.
   21
   22    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   23    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   24    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   25    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   26    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   27    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   28    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   29    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   30    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   32    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   33    POSSIBILITY OF SUCH DAMAGE.
   34*/
   35
   36:- module(ffi,
   37          [ c_import/3,                 % +Header, +Flags, +Functions
   38
   39                                        % Memory access predicates
   40            c_calloc/4,                 % -Ptr, +Type, +Size, +Count
   41            c_free/1,                   % +Ptr
   42            c_disown/1,                 % +Ptr
   43            c_typeof/2,                 % +Ptr, -Type
   44            c_load/4,                   % +Ptr, +Offset, +Type, -Value
   45            c_store/4,                  % +Ptr, +Offset, +Type, +Value
   46            c_offset/6,                 % +Ptr0, +Off, +Type, +Size, +Count, -Ptr
   47            c_sizeof/2,                 % +Type, -Bytes
   48            c_alignof/2,                % +Type, -Bytes
   49            c_address/2,                % +Ptr, -AsInt
   50            c_dim/3,                    % +Ptr, -Count, -ElemSize
   51
   52            c_alloc/2,			% -Ptr, +Type
   53            c_load/2,                   % +Location, -Value
   54            c_store/2,                  % +Location, +Value
   55            c_cast/3,                   % +Type, +PtrIn, -PtrOut
   56            c_nil/1,                    % -Ptr
   57            c_is_nil/1,                 % @Ptr
   58
   59            c_struct/2,                 % +Name, +Fields
   60            c_union/2,                  % +Name, +Fields
   61
   62            c_current_enum/3,           % :Id, ?Enum, ?Value
   63            c_current_struct/1,         % :Name
   64            c_current_struct/3,         % :Name, -Size, -Alignment
   65            c_current_struct_field/4,   % :Name, ?Field, ?Offset, ?Type
   66            c_current_union/1,          % :Name
   67            c_current_union/3,          % :Name, -Size, -Alignment
   68            c_current_union_field/3,    % :Name, ?Field, ?Type
   69            c_current_typedef/2,        % :Name, -Type
   70
   71            c_expand_type/2,            % :TypeIn, -TypeOut
   72            c_type_size_align/3,        % :Type, -Size, -Alignment
   73
   74            c_struct_dict/2,            % ?Ptr,  ?Dict
   75
   76	    c_array_to_list/2,          % +Ptr, -List
   77	    c_array_to_list/3,          % +Ptr, +Count, -List
   78	    c_array_from_list/2,        % -Ptr, +List
   79	    c_array_from_list/3,        % -Ptr, +Count, +List
   80	    c_array_from_compound/2,    % -Ptr,  +Compound
   81	    c_array_from_compound/3,    % -Ptr,  +Count, +Compound
   82	    c_array_to_compound/3,      % +Ptr, +Name, -Compound
   83	    c_array_to_compound/4,      % +Ptr, +Count, +Name, -Compound
   84
   85
   86            c_enum_in/3,                % :Id, +Enum, -Int
   87            c_enum_out/3,               % :Id, +Enum, +Int
   88
   89            c_alloc_string/3,           % -Ptr, +Data, +Encoding
   90            c_load_string/4,            % +Ptr, -Data, +Type, +Encoding
   91            c_load_string/5,            % +Ptr, +Len, -Data, +Type, +Encoding
   92
   93            c_errno/1,                  % -Integer
   94
   95            op(200, fy, *),             % for pointer type declarations
   96            op(100, xfx, ~),            % Type~FreeFunc
   97            op(20, yf, [])
   98          ]).   99:- use_module(library(lists)).  100:- use_module(library(debug)).  101:- use_module(library(error)).  102:- use_module(library(apply)).  103:- use_module(library(process)).  104
  105:- use_module(cdecls).  106:- use_module(clocations).

Bind Prolog predicates to C functions

*/

  111:- meta_predicate
  112    c_alloc(-,:),
  113    c_cast(:,+,-),
  114    c_load(:, -),
  115    c_store(:, +),
  116    c_current_enum(?,:,?),
  117    c_enum_in(+,:,-),
  118    c_enum_out(+,:,+),
  119    c_current_struct(:),
  120    c_current_struct(:,?,?),
  121    c_current_struct_field(:,?,?,?),
  122    c_current_union(:),
  123    c_current_union(:,?,?),
  124    c_current_union_field(:,?,?),
  125    c_current_typedef(:,:),
  126    c_struct_dict(:,?),
  127    c_array_to_list(:,?),
  128    c_array_to_list(:,+,?),
  129    c_array_from_list(:,?),
  130    c_array_from_list(:,+,?),
  131    c_array_from_compound(:,?),
  132    c_array_from_compound(:,+,?),
  133    c_array_to_compound(:,+,?),
  134    c_array_to_compound(:,+,+,?),
  135    c_expand_type(:,:),
  136    type_size(:,-),
  137    c_type_size_align(:,-,-),
  138    c_type_size_align(:,-,-, +).  139
  140
  141:- use_foreign_library(foreign(ffi4pl)).  142
  143:- multifile
  144    user:file_search_path/2,
  145    system:term_expansion/2,
  146    user:exception/3,
  147    c_function/3.  148
  149
  150		 /*******************************
  151		 *           LIBRARIES		*
  152		 *******************************/
 c_library(+Base, -FHandle, +Options)
Find a file handle for a foreign library. If Base is of the form Base-Options pass the options to ffi_library_create/3.
  159:- dynamic  c_library_cache/2.  160:- volatile c_library_cache/2.  161
  162c_library(Base, FHandle, _Options) :-
  163    c_library_cache(Base, FHandle0),
  164    !,
  165    FHandle = FHandle0.
  166c_library(Base, FHandle, Options) :-
  167    with_mutex(ffi, c_library_sync(Base, FHandle, Options)).
  168
  169c_library_sync(Base, FHandle, _Options) :-
  170    c_library_cache(Base, FHandle0),
  171    !,
  172    FHandle = FHandle0.
  173c_library_sync(Base, FHandle, Options) :-
  174    !,
  175    c_lib_path(Base, Path, Options),
  176    convlist(rtld, Options, Flags),
  177    ffi_library_create(Path, FHandle, Flags),
  178    assertz(c_library_cache(Base, FHandle)).
  179
  180rtld(rtld(Flag), Flag).
  181
  182
  183		 /*******************************
  184		 *             IMPORT		*
  185		 *******************************/
 c_import(+Header, +Flags, +Functions)
Import Functions as predicates from Libs based on the declaration from Header.
  192c_import(Header, Flags, Functions) :-
  193        throw(error(context_error(nodirective,
  194                                  c_import(Header, Flags, Functions)), _)).
  195
  196system:term_expansion((:- c_import(Header0, Flags0, Functions0)),
  197                      Clauses) :-
  198    c_macro_expand(c_import(Header0, Flags0, Functions0),
  199                   c_import(Header, Flags1, Functions)),
  200    \+ current_prolog_flag(xref, true),
  201    prolog_load_context(module, M),
  202    phrase(c_functions_needed(Functions), FunctionNames),
  203    add_constants(M, Header, HeaderConst),
  204    expand_flags(Flags1, Flags),
  205    partition(is_lib_flag, Flags, LibFlags, InclFlags),
  206    c99_types(HeaderConst, InclFlags, FunctionNames, Types, Constants),
  207    (   debugging(ffi(types))
  208    ->  print_term(Types, [])
  209    ;   true
  210    ),
  211    phrase(( c_constants(Constants),
  212             c_import(Functions, LibFlags, FunctionNames, Types)),
  213           Clauses).
 expand_flags(+Flags0, -Flags) is det
Expand calls to pkg-config written down as e.g., pkg_config(uchardet, '--cflags', '--libs')
  220expand_flags(Flags0, Flags) :-
  221    must_be(ground, Flags0),
  222    maplist(expand_flag, Flags0, Flags1),
  223    (   Flags0 == Flags1
  224    ->  Flags = Flags0
  225    ;   flatten(Flags1, Flags),
  226        debug(ffi(flags), 'Final flags: ~p', [Flags])
  227    ).
  228
  229expand_flag(Flag, Flags) :-
  230    compound(Flag),
  231    compound_name_arguments(Flag, Name, Args),
  232    pkg_config(Name),
  233    !,
  234    setup_call_cleanup(
  235        process_create(path('pkg-config'), Args,
  236                       [ stdout(pipe(Out)) ]),
  237        read_string(Out, _, String),
  238        close(Out)),
  239    split_string(String, " \r\t\t", " \r\n\t", FlagStrings),
  240    maplist(atom_string, Flags, FlagStrings).
  241expand_flag(Flag, Flag).
  242
  243pkg_config(pkg_config).
  244pkg_config('pkg-config').
 c_functions_needed(+FuncSpecList)//
Get the names of the C functions that we need. Optional functions are returned in a list.
  253c_functions_needed([]) --> [].
  254c_functions_needed([H|T]) --> c_function_needed(H), c_functions_needed(T).
  255
  256c_function_needed([Spec]) -->
  257    !,
  258    c_function_needed(Spec, optional).
  259c_function_needed(Spec) -->
  260    c_function_needed(Spec, required).
  261
  262c_function_needed(Spec as _, Optional) -->
  263    !,
  264    c_function_needed(Spec, Optional).
  265c_function_needed(Spec, Optional) -->
  266    { compound_name_arguments(Spec, Name, Args) },
  267    needed(Name, Optional),
  268    free_needed(Args, Optional).
  269
  270free_needed([], _) --> [].
  271free_needed([H|T], Optional) --> free_arg(H, Optional), free_needed(T, Optional).
  272
  273free_arg(_Type~Free, Optional) -->
  274    !,
  275    needed(Free, Optional).
  276free_arg(*(_Type,Free), Optional) -->   % deprecated
  277    !,
  278    needed(Free, Optional).
  279free_arg([Ret], Optional) -->
  280    !,
  281    free_arg(Ret, Optional).
  282free_arg(-Output, Optional) -->
  283    !,
  284    free_arg(Output, Optional).
  285free_arg(_, _) -->
  286    [].
  287
  288needed(Name, optional) -->
  289    [[Name]].
  290needed(Name, required) -->
  291    [Name].
 c_import(+FuncSpecList, +Flags, +FunctionNames, +Types)//
Produce the clauses for the predicates and types that represent the library.
  298c_import(Functions, Flags, FunctionNames, Types) -->
  299    decls(Types),
  300    compile_types(Types, Types),
  301    wrap_functions(Functions, Types),
  302    libs(Flags, FunctionNames).
  303
  304decls(_) -->
  305    [ (:- discontiguous(('$c_lib'/3,
  306                         '$c_struct'/3,
  307                         '$c_struct_field'/4,
  308                         '$c_union'/3,
  309                         '$c_union_field'/4,
  310                         '$c_enum'/3,
  311                         '$c_typedef'/2
  312                        ))),
  313      (:- dynamic        '$c_symbol_cache'/2,
  314	                 '$c_lib'/3
  315      )
  316    ].
  317
  318compile_types([], _) --> [].
  319compile_types([struct(Name,Fields)|T], Types) --> !,
  320    compile_struct(Name, Fields, Types),
  321    compile_types(T, Types).
  322compile_types([union(Name,Fields)|T], Types) --> !,
  323    compile_union(Name, Fields, Types),
  324    compile_types(T, Types).
  325compile_types([enum(Name, Values)|T], Types) --> !,
  326    compile_enum(Name, Values),
  327    compile_types(T, Types).
  328compile_types([typedef(Name, Type)|T], Types) --> !,
  329    compile_typedef(Name, Type),
  330    compile_types(T, Types).
  331compile_types([_|T], Types) --> !,
  332    compile_types(T, Types).
  333
  334wrap_functions([], _) --> [].
  335wrap_functions([H|T], Types) -->
  336    { optional(H, Func, Optional)
  337    },
  338    wrap_function(Func, Optional, Types),
  339    wrap_functions(T, Types).
  340
  341optional([Func], Func, optional) :- !.
  342optional(Func,   Func, required).
  343
  344wrap_function(Signature as PName, _Optional, Types) -->
  345    !,
  346    (   { compound_name_arguments(Signature, FName, SigArgs),
  347          memberchk(function(FName, CRet0, Params), Types)
  348        }
  349    ->  (   { signature_arity(SigArgs, Arity),
  350              matching_signature(FName, SigArgs, CRet0, CRet,
  351                                 Params, SigParams, Types),
  352              include(is_closure, SigParams, Closures),
  353              length(Closures, NClosures),
  354              PArity is Arity - NClosures,
  355              functor(PHead, PName, PArity),
  356              CSignature =.. [FName|SigParams],
  357              prolog_load_context(module, M)
  358            }
  359        ->  [ ffi:c_function(M:PHead, Params, CRet),
  360              (:- dynamic(PName/PArity)),
  361              (PHead :- ffi:define(M:PHead, CSignature))
  362            ]
  363        ;   []                          % Ignore non-matching signature
  364        )
  365    ;   []                              % Already warned by c99_types
  366    ).
  367wrap_function(Signature, Optional, Types) -->
  368    { compound_name_arity(Signature, Name, _)
  369    },
  370    wrap_function(Signature as Name, Optional, Types).
  371
  372signature_arity(SigArgs, Arity) :-
  373    append(Pre, [[void]], SigArgs),
  374    !,
  375    length(Pre, Arity).
  376signature_arity(SigArgs, Arity) :-
  377    length(SigArgs, Arity).
  378
  379
  380is_closure(+closure(_)).
  381is_closure(+c_callback(_)).
 matching_signature(+FuncName, +PlArgs, +CRet0, -CRet, +CArgs, -SignatureArgs, +Types) is semidet
Match the signature given by the user with the one extracted from the C code. If the two signatures are compatible, the resulting SignatureArgs is a list of arguments using the same notation as PlArgs, but using the concrete C types rather than the abstract Prolog type. For example, Prolog int may be mapped to C ulong if the C function accepts a type that (eventually) aliases to an unsigned long.
  395matching_signature(Name, SigArgs, CRet0, CRet, Params, SigParams, Types) :-
  396    append(RealArgs, [[PlRet]], SigArgs),   % specified return
  397    !,
  398    (   matching_param_length(RealArgs, Params, PlArgs, VArgs, CParams)
  399    ->  maplist(compatible_argument(Name, Types),
  400                PlArgs, CParams, SigRealParams)
  401    ;   print_message(error, ffi(nonmatching_params(Name, SigArgs, Params))),
  402        fail
  403    ),
  404    (   PlRet == void
  405    ->  append(SigRealParams, VArgs, SigParams),
  406        CRet = void
  407    ;   CRet0 == void
  408    ->  print_message(error, ffi(void_function(Name, PlRet))),
  409        fail
  410    ;   compatible_return(Name, PlRet, CRet0, RetParam, Types),
  411        CRet = CRet0,
  412        append([SigRealParams, VArgs, [[RetParam]]], SigParams)
  413    ).
  414matching_signature(Name, SigArgs, CRet, CRet, Params, SigParams, Types) :-
  415    (   matching_param_length(SigArgs, Params, PlArgs, VArgs, CParams)
  416    ->  maplist(compatible_argument(Name, Types),
  417                PlArgs, CParams, SigParams0),
  418        append(SigParams0, VArgs, SigParams)
  419    ;   print_message(error, ffi(nonmatching_params(Name, SigArgs, Params))),
  420        fail
  421    ),
  422    (   CRet == void
  423    ->  true
  424    ;   print_message(warning, ffi(nonvoid_function(Name, CRet)))
  425    ).
 matching_param_length(+PlParms, +CParms, -ReqPlArgs, -VarPlArgs, -RegCParms) is semidet
Check that the argument count of the Prolog specification and C function match.
Arguments:
ReqPlArgs- Prolog arguments that must be matched
VarPlArgs- Prolog variadic arguments (matches against ...)
RegCParms- C arguments that must be matched
  437matching_param_length(PlParms, CParams, ReqPlParams, VarPlParams, ReqCParams) :-
  438    append(ReqCParams, ['...'], CParams),
  439    !,
  440    length(ReqCParams, CArgc),
  441    length(ReqPlParams, CArgc),
  442    append(ReqPlParams, VarPlParams0, PlParms),
  443    maplist(variadic_param, VarPlParams0, VarPlParams).
  444matching_param_length(PlParms, CParams, PlParms, [], CParams) :-
  445    same_length(PlParms, CParams).
  446
  447variadic_param(-Type, -Type) :- !.
  448variadic_param(*(Type), *Type) :- !.
  449variadic_param(Type0, Type) :-
  450    default_promotion(Type0, Type), !.
  451variadic_param(Type, Type).
  452
  453default_promotion(char,    int).
  454default_promotion(schar,   int).
  455default_promotion(uchar,   uint).
  456default_promotion('_Bool', uint).
  457default_promotion(short,   int).
  458default_promotion(ushort,  int).
  459default_promotion(float,   double).
 compatible_argument(+Func, +Types, +PlArg, +CArg, -Param)
  464compatible_argument(_Func, Types, PlArg, CArg, Param) :-
  465    compatible_arg(PlArg, CArg, Param, Types),
  466    !.
  467compatible_argument(_Func, Types, PlArg, CArg, PlArg) :-
  468    compatible_arg(PlArg, CArg, Types),
  469    !.
  470compatible_argument(Func, _, PlArg, CArg, PlArg) :-
  471    print_message(error, ffi(incompatible_argument(Func, PlArg, CArg))).
  472
  473% compatible_arg/4
  474compatible_arg(PlArg, _ArgName-CArg, Param, Types) :-
  475    !,
  476    compatible_arg(PlArg, CArg, Param, Types).
  477compatible_arg(+PlArg, CArg, Param, Types) :-
  478    !,
  479    compatible_arg(PlArg, CArg, Param, Types).
  480compatible_arg(int, CType, +CType, _) :-
  481    int_type(CType).
  482compatible_arg(int, enum(_), +int, _).
  483compatible_arg(enum, enum(Name), +enum(Name), _).
  484compatible_arg(-int, *(CType), -CType, _) :-
  485    int_type(CType).
  486compatible_arg(*int, *(CType), *CType, _) :-
  487    int_type(CType).
  488compatible_arg(bool, '_Bool', +'_Bool', _).
  489compatible_arg(-bool, *('_Bool'), -'_Bool', _).
  490compatible_arg(*bool, *('_Bool'), *'_Bool', _).
  491compatible_arg(float, CType, +CType, _) :-
  492    float_type(CType).
  493compatible_arg(-float, *(CType), -CType, _) :-
  494    float_type(CType).
  495compatible_arg(null, funcptr(_Ret, _Params), +c_callback(_:null), _Types) :-
  496   !.
  497compatible_arg('C'(Callback), funcptr(_Ret, _Params), +c_callback(M:Callback), _Types) :-
  498   prolog_load_context(module, M),
  499   !.
  500compatible_arg(Func0, funcptr(Ret, Params), +closure(M:Func), Types) :-
  501    prolog_load_context(module, M0),
  502    strip_module(M0:Func0, M, Func1),
  503    compound(Func1),
  504    Func1 \= +(_),
  505    Func1 \= *(_),
  506    compound_name_arguments(Func1, Pred, SigArgs),
  507    !,
  508    matching_signature(-, SigArgs, Ret, Ret, Params, SigParams, Types),
  509    compound_name_arguments(Func, Pred, SigParams).
  510% compatible_arg/3
  511compatible_arg(PlArg, _ArgName-CArg, Types) :-
  512    !,
  513    compatible_arg(PlArg, CArg, Types).
  514compatible_arg(+PlArg, CArg, Types) :-
  515    !,
  516    compatible_arg(PlArg, CArg, Types).
  517compatible_arg(Type, Type, _) :- !.
  518compatible_arg(-PType~_Free, *(CType), Types) :- !,
  519    compatible_arg(PType, CType, Types).
  520compatible_arg(-PType, *(CType), Types) :- !,
  521    compatible_arg(PType, CType, Types).
  522compatible_arg(struct(Name),    *(struct(Name)), _).
  523compatible_arg(*struct(Name),   *(struct(Name)), _).
  524compatible_arg(union(Name),     *(union(Name)), _).
  525compatible_arg(*union(Name),    *(union(Name)), _).
  526compatible_arg(char,            schar, _).
  527compatible_arg(string,          *(char), _).
  528compatible_arg(string,          *(schar), _).
  529compatible_arg(string(wchar_t), *(Type), _) :- !, wchar_t_type(Type).
  530compatible_arg(string(Enc),     *(char), _) :- Enc \== wchar_t.
  531compatible_arg(string(Enc),     *(schar), _) :- Enc \== wchar_t.
  532compatible_arg(*TypeName,       CType, Types) :-
  533    atom(TypeName),
  534    memberchk(typedef(TypeName, Type), Types),
  535    !,
  536    compatible_arg(*Type, CType, Types).
  537compatible_arg(TypeName,        CType, Types) :-
  538    atom(TypeName),
  539    memberchk(typedef(TypeName, Type), Types),
  540    !,
  541    compatible_arg(Type, CType, Types).
  542compatible_arg(-TypeName,        CType, Types) :-
  543    atom(TypeName),
  544    memberchk(typedef(TypeName, Type), Types),
  545    !,
  546    compatible_arg(-Type, CType, Types).
  547compatible_arg(*Type, *CType, Types) :-
  548    compatible_arg(Type, CType, Types).
  549
  550
  551compatible_return(_Func, PlArg, CArg, RetParam, Types) :-
  552    compatible_ret(PlArg, CArg, RetParam, Types),
  553    !.
  554compatible_return(_Func, PlArg, CArg, PlArg, Types) :-
  555    compatible_ret(PlArg, CArg, Types),
  556    !.
  557compatible_return(Func, PlArg, CArg, PlArg, _Types) :-
  558    print_message(error, ffi(incompatible_return(Func, PlArg, CArg))).
  559
  560% compatible_ret/4
  561compatible_ret(-PlArg, CArg, Param, Types) :-
  562    compatible_ret(PlArg, CArg, Param, Types).
  563compatible_ret(PlArg~Free, CArg, Param~Free, Types) :-
  564    !,
  565    compatible_ret(PlArg, CArg, Param, Types).
  566compatible_ret(int, CArg, CArg, _) :-
  567    int_type(CArg),
  568    !.
  569compatible_ret(int, enum(_), int, _) :-
  570    !.
  571compatible_ret(bool, '_Bool', '_Bool', _) :-
  572    !.
  573compatible_ret(enum, enum(Name), enum(Name), _) :-
  574    !.
  575compatible_ret(float, CArg, CArg, _) :-
  576    float_type(CArg).
  577compatible_ret(*(TypeName,Free), *(CType), *(CType,Free), Types) :-
  578    !,
  579    compatible_ret(*(TypeName), *(CType), *(CType), Types).
  580compatible_ret(*(TypeName), *(CType), *(CType), Types) :-
  581    memberchk(typedef(TypeName, Type), Types),
  582    !,
  583    compatible_ret(*(Type), *(CType), Types).
  584% compatible_ret/3
  585compatible_ret(-PlArg, CArg, Types) :-
  586    !,
  587    compatible_ret(PlArg, CArg, Types).
  588compatible_ret(Type~_Free, CType, Types) :-
  589    !,
  590    compatible_ret(Type, CType, Types).
  591compatible_ret(*(Type,_Free), CType, Types) :- % deprecated
  592    !,
  593    compatible_ret(*(Type), CType, Types).
  594compatible_ret(Type, Type, _) :- !.
  595compatible_ret(*(char),          *(schar), _).
  596compatible_ret(*(schar),         *(char), _).
  597compatible_ret(atom, CType, Types) :-
  598    compatible_ret(string, CType, Types).
  599compatible_ret(atom(Enc), CType, Types) :-
  600    compatible_ret(string(Enc), CType, Types).
  601compatible_ret(string,           *(char), _).
  602compatible_ret(string,           *(schar), _).
  603compatible_ret(string(wchar_t),  *(Type), _) :- !, wchar_t_type(Type).
  604compatible_ret(string(Enc),      *(char), _) :- Enc \== wchar_t.
  605compatible_ret(string(Enc),      *(schar), _) :- Enc \== wchar_t.
  606
  607int_type(char).
  608int_type(schar).
  609int_type(uchar).
  610int_type(short).
  611int_type(ushort).
  612int_type(int).
  613int_type(uint).
  614int_type(long).
  615int_type(ulong).
  616int_type(longlong).
  617int_type(ulonglong).
  618int_type(size_t).
  619
  620float_type(float).
  621float_type(double).
  622
  623wchar_t_type(Type) :-
  624    c_sizeof(Type, Size),
  625    c_sizeof(wchar_t, Size).
 libs(+Flags, +Functions)// is det
Create '$c_lib'(Lib, Dir, Functions) facts that describe which functions are provided by which library.
  632libs(Flags, Functions) -->
  633    { convlist(flag_lib, Flags, Specs),
  634      partition(load_option, Specs, Options, Libs),
  635      prolog_load_context(directory, Dir)
  636    },
  637    lib_clauses(Libs, Functions, [relative_to(Dir)|Options]).
  638
  639load_option(rtld(_)).
  640
  641lib_clauses([], _, _) --> [].
  642lib_clauses([H|T], Functions, Options) -->
  643    [ '$c_lib'(H, Options, Functions) ],
  644    lib_clauses(T, Functions, Options).
  645
  646is_lib_flag(Flag) :-
  647    flag_lib(Flag, _).
  648
  649flag_lib(Flag, Lib) :-
  650    compound(Flag),
  651    !,
  652    Lib = Flag.
  653flag_lib(Flag, Lib) :-
  654    atom_concat('-l', Rest, Flag),
  655    !,
  656    atom_concat('lib', Rest, Lib).
  657flag_lib(Flag, Lib) :-
  658    atom_concat('--rtld_', Opt, Flag),
  659    !,
  660    Lib = rtld(Opt).
  661flag_lib(Lib, Lib) :-
  662    \+ sub_atom(Lib, 0, _, _, '-').
 define(:Head, +CSignature)
Actually link the C function
  668:- public
  669    define/2.  670
  671define(QHead, CSignature) :-
  672    QHead = M:_Head,
  673    link_clause(QHead, CSignature, Clause),
  674    !,
  675    asserta(M:Clause),
  676    call(QHead).
  677define(QHead, _) :-
  678    throw(error(ffi_error(define(QHead)), _)).
  679
  680link_clause(M:Goal, CSignature,
  681            (PHead :- !, Body)) :-
  682    c_function(M:Goal, ParamSpec, RetType),	% Also in dynamic part?
  683    maplist(strip_param_name, ParamSpec, ParamTypes),
  684    functor(Goal, Name, PArity),
  685    functor(PHead, Name, PArity),
  686    functor(CSignature, _, CArity),
  687    functor(CHead, Name, CArity),
  688    CSignature =.. [FName|SigArgs],
  689    find_symbol(M, FName, FuncPtr),
  690    prototype_types(ParamTypes, SigArgs, RetType, M, PParams, PRet),
  691    debug(ffi(prototype),
  692          'Binding ~p (Ret=~p, Params=~p)', [Name, PRet, PParams]),
  693    ffi_prototype_create(FuncPtr, default, PRet, PParams, Prototype),
  694    convert_args(SigArgs, 1, PArity, 1, CArity, PHead, CHead,
  695                 PreConvert, PostConvert),
  696    Invoke = ffi:ffi_call(Prototype, CHead),
  697    mkconj(PreConvert, Invoke, Body0),
  698    mkconj(Body0, PostConvert, Body).
  699
  700strip_param_name(_Name-Type, Type) :- !.
  701strip_param_name(Type, Type).
  702
  703find_symbol(M, FName, Symbol) :-
  704    M:'$c_lib'(Lib, Options, Funcs),
  705    member(Func, Funcs),
  706    optional(Func, FName, _Optional),
  707    c_library(Lib, FH, Options),
  708    ffi_lookup_symbol(FH, FName, Symbol),
  709    !.
  710find_symbol(_, FName, _) :-
  711    existence_error(c_function, FName).
 prototype_types(+CParms, +PlParms, +CRet, +Module, -CTypes, -CRetType)
Create the argument and return type specification for the prototype.
  718prototype_types([], [[SA]], RetType, M, [], PRet) :-
  719    !,
  720    prototype_type(RetType, M, SA, PRet).
  721prototype_types([], [], _RetType, _M, [], void).
  722prototype_types([...], PlParms, CRet, M, CTypes, CRetType) :-
  723    !,
  724    variadic_prototypes(PlParms, CRet, M, CTypes, CRetType).
  725prototype_types([H0|T0], [SA|ST], RetType, M, [H|T], PRet) :-
  726    prototype_type(H0, M, SA, H),
  727    prototype_types(T0, ST, RetType, M, T, PRet).
  728
  729variadic_prototypes([[SA]], RetType, M, [], PRet) :-
  730    !,
  731    prototype_type(RetType, M, SA, PRet).
  732variadic_prototypes([], _, _, [], void).
  733variadic_prototypes([SA|ST], RetType, M, [H|T], CRetType) :-
  734    variadic_prototype(SA, M, H),
  735    variadic_prototypes(ST, RetType, M, T, CRetType).
  736
  737variadic_prototype(string, _, *(char)) :- !.
  738variadic_prototype(Type,   _, Type).
 prototype_type(+CType, +Module, +PrologType, -ParamType) is det
  742prototype_type(funcptr(_,_), _, +c_callback(_), c_callback) :-
  743    !.
  744prototype_type(funcptr(_,_), _, PlType, closure) :-
  745    compound_name_arguments(PlType, _, _),
  746    !.
  747prototype_type(*(*CType), M, -OutputType~FreeName, -(*(CType,Free))) :-
  748    c_output_argument_type(OutputType),
  749    find_symbol(M, FreeName, Free),
  750    !.
  751prototype_type(*CType, _, -OutputType, -CType) :-
  752    c_output_argument_type(OutputType),
  753    !.
  754prototype_type(*Type0, M, Sig, *Type) :-
  755    !,
  756    prototype_type(Type0, M, Sig, Type).
  757prototype_type(*(Type0, Free), M, Sig, *(Type, Free)) :-
  758    !,
  759    prototype_type(Type0, M, Sig, Type).
  760prototype_type(struct(Name), M, _Sig, struct(Name, Size)) :-
  761    !,
  762    catch(type_size(M:struct(Name), Size),
  763          error(existence_error(type,_),_),
  764          Size = 0).
  765prototype_type(union(Name), M, _Sig, union(Name, Size)) :-
  766    !,
  767    catch(type_size(M:union(Name), Size),
  768          error(existence_error(type,_),_),
  769          Size = 0).
  770prototype_type(Type, _, _, Type).
  771
  772c_output_argument_type(ScalarType) :-
  773    c_sizeof(ScalarType, _Size).
  774c_output_argument_type(enum(_)).
  775c_output_argument_type(string).
  776c_output_argument_type(string(_Encoding)).
  777c_output_argument_type(atom).
  778c_output_argument_type(atom(_Encoding)).
  779c_output_argument_type(*(_)).
 convert_args(+SigArgs, +PI, +PArity, +CI, +CArity, +PlHead, +CHead, -PreGoal, -PostGoal)
Establish the conversions between the Prolog head and the C head.
  787convert_args([], _, _, _, _, _, _, true, true).
  788convert_args([+closure(M:Closure)|T], PI, PArity, CI, CArity,
  789             PHead, CHead, GPre, GPost) :-
  790    !,
  791    arg(CI, CHead, CClosure),
  792    closure_create(M:Closure, CClosure),
  793    CI2 is CI + 1,
  794    convert_args(T, PI, PArity, CI2, CArity, PHead, CHead, GPre, GPost).
  795convert_args([+c_callback(M:Callback)|T], PI, PArity, CI, CArity,
  796             PHead, CHead, GPre, GPost) :-
  797    !,
  798    arg(CI, CHead, CCallback),
  799    ccallback_create(M:Callback, CCallback),
  800    CI2 is CI + 1,
  801    convert_args(T, PI, PArity, CI2, CArity, PHead, CHead, GPre, GPost).
  802convert_args([H|T], PI, PArity, CI, CArity, PHead, CHead, GPre, GPost) :-
  803    arg(PI, PHead, PArg),
  804    arg(CI, CHead, CArg),
  805    (   convert_arg(H, PArg, CArg, GPre1, GPost1)
  806    ->  true
  807    ;   PArg = CArg,
  808        GPre1 = true,
  809        GPost1 = true
  810    ),
  811    PI2 is PI + 1,
  812    CI2 is CI + 1,
  813    convert_args(T, PI2, PArity, CI2, CArity, PHead, CHead, GPre2, GPost2),
  814    mkconj(GPre1, GPre2, GPre),
  815    mkconj(GPost1, GPost2, GPost).
  816
  817% parameter values
  818convert_arg(+Type, Prolog, C, Pre, Post) :-
  819    !,
  820    convert_arg(Type, Prolog, C, Pre, Post).
  821convert_arg(-Type~_Free, Prolog, C, Pre, Post) :-
  822    !,
  823    convert_arg(-Type, Prolog, C, Pre, Post).
  824convert_arg(-struct(Name), Ptr, Ptr,
  825            c_alloc(Ptr, struct(Name)),
  826            true).
  827convert_arg(-union(Name), Ptr, Ptr,
  828            c_alloc(Ptr, union(Name)),
  829            true).
  830convert_arg(-string, String, Ptr,
  831            true,
  832            c_load_string(Ptr, String, string, text)).
  833convert_arg(-string(Enc), String, Ptr,
  834            true,
  835            c_load_string(Ptr, String, string, Enc)).
  836convert_arg(-atom, String, Ptr,
  837            true,
  838            c_load_string(Ptr, String, atom, text)).
  839convert_arg(-atom(Enc), String, Ptr,
  840            true,
  841            c_load_string(Ptr, String, atom, Enc)).
  842convert_arg(string(Enc),  String, Ptr,
  843            c_alloc_string(Ptr, String, Enc),
  844            true).
  845convert_arg(string, String, Ptr, Pre, Post) :-
  846    convert_arg(string(text), String, Ptr, Pre, Post).
  847convert_arg(enum(Enum), Id, Int,
  848            c_enum_in(Id, Enum, Int),
  849            true).
  850convert_arg(-enum(Enum), Id, Int,
  851            true,
  852            c_enum_out(Id, Enum, Int)).
  853
  854% return value.  We allow for -Value, but do not demand it as the
  855% return value can only be an output.
  856convert_arg([-(X)], Out, In, Pre, Post) :-
  857    !,
  858    convert_arg([X], Out, In, Pre, Post).
  859convert_arg([Type~_Free], Out, In, Pre, Post) :-
  860    !,
  861    convert_arg([Type], Out, In, Pre, Post).
  862convert_arg([string(Enc)], String, Ptr,
  863            true,
  864            c_load_string(Ptr, String, string, Enc)).
  865convert_arg([string], String, Ptr, Pre, Post) :-
  866    convert_arg([-string(text)], String, Ptr, Pre, Post).
  867convert_arg([atom(Enc)], String, Ptr,
  868            true,
  869            c_load_string(Ptr, String, atom, Enc)).
  870convert_arg([atom], String, Ptr, Pre, Post) :-
  871    convert_arg([-atom(text)], String, Ptr, Pre, Post).
  872convert_arg([enum(Enum)], Id, Int,
  873            true,
  874            c_enum_out(Id, Enum, Int)).
  875
  876mkconj(true, G, G) :- !.
  877mkconj(G, true, G) :- !.
  878mkconj(G1, G2, (G1,G2)).
 callback_create(:Head, -Closure) is det
Create a C callback pointer from Head. Head is a qualified term of the form 'C'(Callback), where Callback is a term with a functor which is the name of the C function to call, and the parameterts are the callback parameter types, which are used during parsing only for type checking.
  889ccallback_create(_:null, CCallback) :-
  890    ffi:ffi_callback_ptr(_FH, '$null_callback', CCallback).
  891ccallback_create(M:CHead, CCallback) :-
  892    compound_name_arguments(CHead, CFuncName, _),
  893    c_symbol_callback(M:CFuncName,CCallback).
  894
  895%  Lookup C symbol address in shared libraries that have
  896%  been loaded by c_import in the context of module M.
  897c_symbol_callback(M:Symbol, CCallback) :-
  898    M:'$c_symbol_cache'(Symbol, CCallback),
  899    !.
  900c_symbol_callback(M:Symbol, CCallback) :-
  901    M:'$c_lib'(Lib, Options, _),
  902    c_library(Lib, FH, Options),
  903    ffi:ffi_callback_ptr(FH, Symbol, CCallback),
  904    M:assert('$c_symbol_cache'(Symbol, CCallback)),
  905    debug(ffi(callback), '~p', [symcb(FH,Symbol,CCallback)]).
 closure_create(:Head, -Closure) is det
Create a closure object from Head. Head is a qualified term whose functor is the predicate name to be called and whose arguments are the C parameter types.
  913closure_create(M:Head, Closure) :-
  914    compound_name_arguments(Head, _, Args),
  915    (   append(Params0, [[Return]], Args)
  916    ->  true
  917    ;   Params0 = Args,
  918        Return = void
  919    ),
  920    maplist(strip_mode, Params0, Params),
  921    ffi_closure_create(M:Head, default, Return, Params, Closure).
  922
  923strip_mode(+Type, Type) :- !.
  924strip_mode(Type, Type).
  925
  926
  927		 /*******************************
  928		 *          STRUCTURES		*
  929		 *******************************/
 c_struct(+Name, +Fields)
Declare a C structure with name Name. Fields is a list of field specifications of the form:

Where Type is one of

This directive is normally used by c_import/3 to create type information for structures that are involved in functions that are imported. This directive may be used explicitly in combination with the C memory access predicates to read or write memory using C binary representation.

  953c_struct(Name, Fields) :-
  954    throw(error(context_error(nodirective, c_struct(Name, Fields)), _)).
  955
  956system:term_expansion((:- c_struct(Name, Fields)), Clauses) :-
  957    phrase(compile_structs([struct(Name, Fields)]), Clauses).
  958
  959compile_structs(List) -->
  960    compile_structs(List, List).
  961
  962compile_structs([], _) --> [].
  963compile_structs([struct(Name,Fields)|T], All) -->
  964    compile_struct(Name, Fields, All),
  965    compile_structs(T, All).
  966
  967compile_struct(Name, Fields, All) -->
  968    field_clauses(Fields, Name, 0, End, 0, Alignment, All),
  969    { Size is Alignment*((End+Alignment-1)//Alignment) },
  970    [ '$c_struct'(Name, Size, Alignment) ].
  971
  972field_clauses([], _, End, End, Align, Align, _) --> [].
  973field_clauses([f(Name,bitfield(Width))|T0], Struct,
  974              Off0, Off, Align0, Align, All) --> !,
  975    { c_type_size_align(uint, Size, Alignment, All),
  976      Bits is 8*Size,
  977      Align1 is max(Align0, Alignment),
  978      Off1 is Alignment*((Off0+Alignment-1)//Alignment),
  979      Off2 is Off1 + Size
  980    },
  981    bitfield_clauses([f(Name,bitfield(Width))|T0], Struct,
  982                     Off1, 0, Bits, T),
  983    field_clauses(T, Struct, Off2, Off, Align1, Align, All).
  984field_clauses([f(Name,Type)|T], Struct, Off0, Off, Align0, Align, All) -->
  985    { c_type_size_align(Type, Size, Alignment, All),
  986      Align1 is max(Align0, Alignment),
  987      Off1 is Alignment*((Off0+Alignment-1)//Alignment),
  988      Off2 is Off1 + Size
  989    },
  990    [ '$c_struct_field'(Struct, Name, Off1, Type) ],
  991    field_clauses(T, Struct, Off2, Off, Align1, Align, All).
  992
  993bitfield_clauses([f(Name,bitfield(Width))|T0], Struct,
  994                 IntOffset, BitsUsed, Bits, T) -->
  995    { BitsUsed1 is BitsUsed + Width,
  996      BitsUsed1 =< Bits
  997    },
  998    [ '$c_struct_field'(Struct, Name, IntOffset, bitfield(BitsUsed, Width)) ],
  999    bitfield_clauses(T0, Struct, IntOffset, BitsUsed1, Bits, T).
 1000bitfield_clauses(Fields, _, _, _, _, Fields) --> [].
 c_union(+Name, +Fields)
Declare a C union with name Name. Fields is a list of fields using the same conventions as c_struct/2.
 1008c_union(Name, Fields) :-
 1009    throw(error(context_error(nodirective, c_union(Name, Fields)), _)).
 1010
 1011system:term_expansion((:- c_union(Name, Fields)), Clauses) :-
 1012    phrase(compile_unions([union(Name, Fields)]), Clauses).
 1013
 1014compile_unions(List) -->
 1015    compile_unions(List, List).
 1016
 1017compile_unions([], _) --> [].
 1018compile_unions([union(Name,Fields)|T], All) -->
 1019    compile_union(Name, Fields, All),
 1020    compile_unions(T, All).
 1021
 1022compile_union(Name, Fields, All) -->
 1023    ufield_clauses(Fields, Name, 0, Size, 0, Alignment, All),
 1024    { Size is Alignment*((Size+Alignment-1)//Alignment) },
 1025    [ '$c_union'(Name, Size, Alignment) ].
 1026
 1027ufield_clauses([], _, Size, Size, Align, Align, _) --> [].
 1028ufield_clauses([f(Name,Type)|T], Struct, Size0, Size, Align0, Align, All) -->
 1029    { c_type_size_align(Type, ESize, Alignment, All),
 1030      Align1 is max(Align0, Alignment),
 1031      Size1  is max(Size0, ESize)
 1032    },
 1033    [ '$c_union_field'(Struct, Name, Type) ],
 1034    ufield_clauses(T, Struct, Size1, Size, Align1, Align, All).
 type_size(:Type, -Size)
Size is the size of an object of Type.
 1041type_size(Type, Size) :-
 1042    c_type_size_align(Type, Size, _).
 c_type_size_align(:Type, -Size, -Alignment) is det
True when Type must be aligned at Alignment and is of size Size.
 1048c_type_size_align(Type, Size, Alignment) :-
 1049    c_type_size_align(Type, Size, Alignment, []).
 1050
 1051c_type_size_align(_:Type, Size, Alignment, _All) :-
 1052    c_alignof(Type, Alignment),
 1053    !,
 1054    c_sizeof(Type, Size).
 1055c_type_size_align(_:struct(Name), Size, Alignment, All) :-
 1056    memberchk(struct(Name, Fields), All), !,
 1057    phrase(compile_struct(Name, Fields, All), Clauses),
 1058    memberchk('$c_struct'(Name, Size, Alignment), Clauses).
 1059c_type_size_align(_:struct(Name, Fields), Size, Alignment, All) :-
 1060    phrase(compile_struct(Name, Fields, All), Clauses),
 1061    memberchk('$c_struct'(Name, Size, Alignment), Clauses).
 1062c_type_size_align(_:union(Name), Size, Alignment, All) :-
 1063    memberchk(union(Name, Fields), All), !,
 1064    phrase(compile_union(Name, Fields, All), Clauses),
 1065    memberchk('$c_union'(Name, Size, Alignment), Clauses).
 1066c_type_size_align(_:union(Name, Fields), Size, Alignment, All) :-
 1067    phrase(compile_union(Name, Fields, All), Clauses),
 1068    memberchk('$c_union'(Name, Size, Alignment), Clauses).
 1069c_type_size_align(M:struct(Name), Size, Alignment, _) :-
 1070    current_predicate(M:'$c_struct'/3),
 1071    M:'$c_struct'(Name, Size, Alignment),
 1072    !.
 1073c_type_size_align(M:union(Name), Size, Alignment, _) :-
 1074    current_predicate(M:'$c_union'/3),
 1075    M:'$c_union'(Name, Size, Alignment),
 1076    !.
 1077c_type_size_align(M:array(Type,Len), Size, Alignment, All) :-
 1078    !,
 1079    c_type_size_align(M:Type, Size0, Alignment, All),
 1080    Size is Size0*Len.
 1081c_type_size_align(_:enum(_Enum), Size, Alignment, _) :-
 1082    !,
 1083    c_alignof(int, Alignment),
 1084    c_sizeof(int, Size).
 1085c_type_size_align(_:(*(_)), Size, Alignment, _) :-
 1086    !,
 1087    c_alignof(pointer, Alignment),
 1088    c_sizeof(pointer, Size).
 1089c_type_size_align(_:funcptr(_Ret,_Params), Size, Alignment, _) :-
 1090    !,
 1091    c_alignof(pointer, Alignment),
 1092    c_sizeof(pointer, Size).
 1093c_type_size_align(Type, Size, Alignment, All) :-
 1094    c_current_typedef(Type, Def),
 1095    !,
 1096    c_type_size_align(Def, Size, Alignment, All).
 1097c_type_size_align(Type, _Size, _Alignment, _) :-
 1098    existence_error(type, Type).
 c_expand_type(:TypeIn, :TypeOut)
Expand user defined types to arrive at the core type.
 1104c_expand_type(M:Type0, M:Type) :-
 1105    (   base_type(Type0)
 1106    ->  Type0 = Type
 1107    ;   expand_type(Type0, Type, M)
 1108    ).
 1109
 1110base_type(struct(_)).
 1111base_type(union(_)).
 1112base_type(enum(_)).
 1113base_type(Type) :-
 1114    c_sizeof(Type, _).
 1115
 1116expand_type(*Type0, *Type, M) :-
 1117    !,
 1118    (   base_type(Type0)
 1119    ->  Type0 = Type
 1120    ;   expand_type(Type0, Type, M)
 1121    ).
 1122expand_type(Type0, Type, M) :-
 1123    c_current_typedef(M:Type0, M:Type).
 c_current_struct(:Name) is nondet
 c_current_struct(:Name, ?Size, ?Align) is nondet
Total size of the struct in bytes and alignment restrictions.
 1130c_current_struct(Name) :-
 1131    c_current_struct(Name, _, _).
 1132c_current_struct(M:Name, Size, Align) :-
 1133    current_predicate(M:'$c_struct'/3),
 1134    M:'$c_struct'(Name, Size, Align).
 c_current_struct_field(:Name, ?Field, ?Offset, ?Type)
Fact to provide efficient access to fields
 1140c_current_struct_field(M:Name, Field, Offset, M:Type) :-
 1141    current_predicate(M:'$c_struct_field'/4),
 1142    M:'$c_struct_field'(Name, Field, Offset, Type).
 c_current_union(:Name) is nondet
 c_current_union(:Name, ?Size, ?Align) is nondet
Total size of the union in bytes and alignment restrictions.
 1150c_current_union(Name) :-
 1151    c_current_union(Name, _, _).
 1152c_current_union(M:Name, Size, Align) :-
 1153    current_predicate(M:'$c_union'/3),
 1154    M:'$c_union'(Name, Size, Align).
 c_current_union_field(:Name, ?Field, ?Type)
Fact to provide efficient access to fields
 1160c_current_union_field(M:Name, Field, M:Type) :-
 1161    current_predicate(M:'$c_union_field'/3),
 1162    M:'$c_union_field'(Name, Field, Type).
 c_alloc(-Ptr, :TypeAndInit) is det
Allocate memory for a C object of Type and optionally initialse the data. TypeAndInit can take several forms:
A plain type
Allocate an array to hold a single object of the given type.
Type[Count]
Allocate an array to hold Count objects of Type.
Type[] = Init
If Init is data that can be used to initialize an array of objects of Type, allocate an array of sufficient size and initialize each element with data from Init. The following combinations of Type and Init are supported:
char[] = Text
Where Text is a valid Prolog representation for text: an atom, string, list of character codes or list of characters. The Prolog Unicode data is encoded using the native multibyte encoding of the OS.
char(Encoding)[] = Text
Same as above, using a specific encoding. Encoding is one of text (as above), utf8 or iso_latin_1.
Type[] = List
If Data is a list, allocate an array of the length of the list and store each element in the corresponding location of the array.
Type = Value
Same as Type[] = [Value].
To be done
- : error generation
- : support enum and struct initialization from atoms and dicts.
 1204c_alloc(Ptr, M:(Type = Data)) :-
 1205    !,
 1206    c_init(M:Type, Data, Ptr).
 1207c_alloc(M:Ptr, M:Type[Count]) :-
 1208    !,
 1209    type_size(M:Type, Size),
 1210    c_calloc(Ptr, Type, Size, Count).
 1211c_alloc(Ptr, M:Type) :-
 1212    c_expand_type(M:Type, M:Type1),
 1213    type_size(M:Type1, Size),
 1214    c_calloc(Ptr, M:Type1, Size, 1).
 1215
 1216c_init(M:Type[], Data, Ptr) :-
 1217    !,
 1218    c_init_array(M:Type, Data, Ptr).
 1219c_init(M:Type0, Data, Ptr) :-
 1220    atom(Type0),				% primitive type
 1221    !,
 1222    (   c_sizeof(Type0, Size)
 1223    ->  Type = Type0
 1224    ;   c_current_typedef(M:Type0, M:Type),
 1225        c_sizeof(Type, Size)
 1226    ),
 1227    c_calloc(Ptr, Type, Size, 1),
 1228    c_store(Ptr, 0, Type, Data).
 1229c_init(Type, Data, Ptr) :-                      % user types
 1230    Type = M:_,
 1231    type_size(Type, Size),
 1232    c_calloc(Ptr, Type, Size, 1),
 1233    c_store(M:Ptr, Data).
 c_init_array(+Type, +Data, -Ptr) is det
Create an array of objects from data in the list Data.
 1239c_init_array(_:char, Data, Ptr) :-
 1240    !,
 1241    c_alloc_string(Ptr, Data, text).
 1242c_init_array(_:char(Encoding), Data, Ptr) :-
 1243    !,
 1244    c_alloc_string(Ptr, Data, Encoding).
 1245c_init_array(_:wchar_t, Data, Ptr) :-
 1246    !,
 1247    c_alloc_string(Ptr, Data, wchar_t).
 1248c_init_array(_:Type, List, Ptr) :-
 1249    atom(Type),                                 % primitive type
 1250    !,
 1251    is_list(List),
 1252    length(List, Len),
 1253    type_size(Type, Size),
 1254    c_calloc(Ptr, Type, Size, Len),
 1255    fill_array_fast(List, 0, Ptr, Size, Type).
 1256c_init_array(Type, List, Ptr) :-                % arbitrary types
 1257    is_list(List),
 1258    length(List, Len),
 1259    type_size(Type, Size),
 1260    c_calloc(Ptr, Type, Size, Len),
 1261    fill_array(List, 0, Ptr, Size, Type).
 1262
 1263fill_array_fast([], _, _, _, _).
 1264fill_array_fast([H|T], Offset, Ptr, Size, Type) :-
 1265    c_store(Ptr, Offset, Type, H),
 1266    Offset2 is Offset+Size,
 1267    fill_array_fast(T, Offset2, Ptr, Size, Type).
 1268
 1269fill_array([], _, _, _, _).
 1270fill_array([H|T], Offset, Ptr, Size, Type) :-
 1271    c_store(Ptr[Offset], H),
 1272    Offset2 is Offset+1,
 1273    fill_array(T, Offset2, Ptr, Size, Type).
 c_load(:Location, -Value) is det
Load a C value indirect from Location. Location is a pointer, postfixed with zero or more one-element lists. Like JavaScript, the array postfix notation is used to access array elements as well as struct or union fields. Value depends on the type of the addressed location:
TypeProlog value

scalarnumber
structpointer
unionpointer
enumatom
pointerpointer
 1293c_load(Spec, Value) :-
 1294    c_address(Spec, Ptr, Offset, Type),
 1295    c_load_(Ptr, Offset, Type, Value).
 1296
 1297c_load_(Ptr, Offset, Type, Value) :-
 1298    Type = M:Plain,
 1299    (   atom(Plain)
 1300    ->  c_load(Ptr, Offset, Plain, Value)
 1301    ;   compound_type(Plain)
 1302    ->  type_size(Type, Size),
 1303        c_offset(Ptr, Offset, Type, Size, 1, Value)
 1304    ;   Plain = array(EType, Len)
 1305    ->  type_size(Type, ESize),
 1306        c_offset(Ptr, Offset, EType, ESize, Len, Value)
 1307    ;   Plain = enum(Enum)
 1308    ->  c_load(Ptr, Offset, int, IntValue),
 1309        c_enum_out(Value, M:Enum, IntValue)
 1310    ;   Plain = *(PtrType)
 1311    ->  c_load(Ptr, Offset, pointer(PtrType), Value)
 1312    ;   Plain = funcptr(_RetType, _ArgsTypes)   % TBD: represent in closure?
 1313    ->  c_load(Ptr, Offset, pointer(closure), Value)
 1314    ;   domain_error(type, Type)
 1315    ).
 1316
 1317compound_type(struct(_)).
 1318compound_type(union(_)).
 c_store(:Location, +Value)
Store a C value indirect at Location. See c_load/2 for the location syntax. In addition to the conversions provided by c_load/2, c_store/2 supports setting a struct field to a closure. Consider the following declaration:
struct demo_func
{ int (*mul_i)(int, int);
};

We can initialise an instance of this structure holding a C function pointer that calls the predicate mymul/3 as follows:

    c_alloc(Ptr, struct(demo_func)),
    c_store(Ptr[mul_i], mymul(int, int, [int])),
 1341c_store(Spec, Value) :-
 1342    c_address(Spec, Ptr, Offset, Type),
 1343    c_store_(Ptr, Offset, Type, Value).
 1344
 1345c_store_(Ptr, Offset, Type, Value) :-
 1346    Type = M:Plain,
 1347    (   atom(Plain)
 1348    ->  c_store(Ptr, Offset, Plain, Value)
 1349    ;   Plain = enum(Set)
 1350    ->  c_enum_in(Value, M:Set, IntValue),
 1351        c_store(Ptr, Offset, int, IntValue)
 1352    ;   Plain = *(_EType)                       % TBD: validate
 1353    ->  c_store(Ptr, Offset, pointer, Value)
 1354    ;   ( Plain = funcptr(_Ret, _Params), blob(Value,c_ptr) )
 1355    ->  c_store(Ptr, Offset, pointer, Value)    % C callback
 1356    ;   Plain = funcptr(Ret, Params)
 1357    ->  strip_module(M:Value, PM, Func1),       % ffi closure
 1358        compound_name_arguments(Func1, Pred, SigArgs),
 1359        matching_signature(-, SigArgs, Ret, Ret, Params, SigParams, []),
 1360        compound_name_arguments(Func, Pred, SigParams),
 1361        closure_create(PM:Func, Closure),
 1362        c_store(Ptr, Offset, closure, Closure)
 1363    ).
 c_cast(:Type, +PtrIn, -PtrOut)
Cast a pointer. Type is one of:
 1377c_cast(_:Type, _, _) :-
 1378    var(Type),
 1379    !,
 1380    type_error(c_type, Type).
 1381c_cast(_:address, In, Out) :-
 1382    !,
 1383    c_address(In, Out).
 1384c_cast(M:Type[Count], In, Out) :-
 1385    !,
 1386    type_size(M:Type, Size),
 1387    c_offset(In, 0, Type, Size, Count, Out).
 1388c_cast(Type, In, Out) :-
 1389    type_size(Type, Size),
 1390    c_offset(In, 0, Type, Size, _, Out).
 c_nil(-Ptr) is det
Unify Ptr with a (void) NULL pointer.
 c_is_nil(@Ptr) is semidet
True when Ptr is a pointer object representing a NULL pointer.
 c_address(+Spec, -Ptr, -Offset, -Type)
Translate a specification into a pointer, offset and type.
 1404c_address(_:(M2:Spec)[E], Ptr, Offset, Type) :-
 1405    !,                                  % may get wrongly qualified
 1406    c_address(M2:Spec[E], Ptr, Offset, Type).
 1407c_address(M:Spec[E], Ptr, Offset, Type) :-
 1408    !,
 1409    c_address(M:Spec, Ptr0, Offset0, Type0),
 1410    (   atom(E)
 1411    ->  c_member(Type0, E, Ptr0, Offset0, Ptr, Offset, Type)
 1412    ;   integer(E)
 1413    ->  c_array_element(Type0, E, Ptr0, Offset0, Ptr, Offset, Type)
 1414    ;   type_error(member_selector, E)
 1415    ).
 1416c_address(M:Ptr, Ptr, 0, M:Type) :-
 1417    c_typeof(Ptr, Type).
 1418
 1419c_array_element(M:array(EType,Size), E, Ptr, Offset0, Ptr, Offset, M:EType) :-
 1420    !,
 1421    (   E >= 0,
 1422        E < Size
 1423    ->  type_size(M:EType, ESize),
 1424        Offset is Offset0+E*ESize
 1425    ;   domain_error(array(EType,Size), E)
 1426    ).
 1427c_array_element(Type, E, Ptr, Offset0, Ptr, Offset, Type) :-
 1428    type_size(Type, ESize),
 1429    Offset is Offset0+E*ESize.
 1430
 1431c_member(M:struct(Struct), Field, Ptr, Offset0, Ptr, Offset, EType) :-
 1432    !,
 1433    c_current_struct_field(M:Struct, Field, FOffset, EType),
 1434    Offset is Offset0+FOffset.
 1435c_member(M:union(Union), Field, Ptr, Offset, Ptr, Offset, EType) :-
 1436    !,
 1437    c_current_union_field(M:Union, Field, EType).
 1438c_member(Type, _, _, _, _, _, _) :-
 1439    domain_error(struct_or_union, Type).
 1440
 1441		 /*******************************
 1442		 *             LIST		*
 1443		 *******************************/
 c_array_to_list(:Array, -List)
Convert a C array indicated by a sized c_ptr to a prolog list.

Examples:

% C int array to list
?- c_alloc(CPtr, int[]=[3,1,0,2]), c_array_to_list(CPtr,R).
CPtr = <C int[4]>(0x5629848165c0),
R = [3, 1, 0, 2].
 1458c_array_to_list(M:Ptr, List) :-
 1459   nonvar(Ptr),
 1460   !,
 1461   c_array_list2(M:Ptr,List).
 c_array_to_list(:Array, +Count, -List)
Convert a C array indicated by a sized c_ptr to a prolog list.

Examples:

% C int array to list
?- c_alloc(CPtr, int[]=[3,1,0,2]), c_array_to_list(CPtr,2,R).
CPtr = <C int[4]>(0x5629848165c0),
R = [3, 1, 0, 2].
 1477c_array_to_list(M:Ptr, Count, List) :-
 1478   nonvar(Ptr),
 1479   !,
 1480   c_array_list3(M:Ptr,Count,List).
 c_array_from_list(:Array, +List)
Unify Array with a c_ptr that points to a C array with the elements of List.

For now only numeric elements are supported.

Examples:

?- c_array_from_list(Ptr,[3,2,0]).
Ptr = <C long[3]>(0x55a265c6c3e0).
 1496c_array_from_list(_:Ptr, List) :-
 1497   nonvar(List),
 1498   list_numeric(List,CTyp),
 1499   !,
 1500   c_alloc(Ptr,CTyp[]=List).
 c_array_from_list(:Array, +Count, -List)
Unify Array with a c_ptr that points to a C array with Count elements from List.

For now only numeric elements are supported.

Examples:

?- c_array_from_list(Ptr,2,[3,2,0]).
Ptr = <C long[2]>(0x55a265c494c0).
 1516c_array_from_list(_:Ptr, Count, List) :-
 1517   nonvar(List),
 1518   list_numeric(List,CTyp),
 1519   length(L,Count),
 1520   prefix(L,List),
 1521   !,
 1522   c_alloc(Ptr,CTyp[]=L).
 1523
 1524c_array_list_type(_:Ptr, List, CTyp) :-
 1525   nonvar(List),
 1526   !,
 1527   c_alloc(Ptr,CTyp[]=List).
 1528
 1529
 1530list_numeric([H|_],long) :-
 1531   integer(H).
 1532
 1533list_numeric([H|_],double) :-
 1534   float(H).
 c_array_to_compound(:Ptr, +Name, -Compound)
Unify Compound with arguments obtained from the C array pointed by the sized c_ptr Ptr.

Example

?- c_alloc(Arr,int[]=[3,0,1]), c_array_to_compound(Arr,myterm,C).
Arr = <C int[3]>(0x561f2497ff00),
C = myterm(3, 0, 1).
 1549c_array_to_compound(M:Ptr, Name, Compound) :-
 1550   nonvar(Ptr),
 1551   !,
 1552   c_array_compound3(M:Ptr,Name,Compound).
 c_array_to_compound(:Ptr, +Count, +Name, -Compound)
Unify Compound with Count arguments obtained from the C array pointed by the Ptr. Ptr can be an unsized c_ptr (e.g. a c_ptr containing *int).

Example

?- c_alloc(Arr,int[]=[3,0,1]), c_array_to_compound(Arr,2,myterm,C).
Arr = <C int[3]>(0x561f2497fc00),
C = myterm(3, 0).
 1568c_array_to_compound(M:Ptr, Count, Name, Compound) :-
 1569   nonvar(Ptr),
 1570   !,
 1571   c_array_compound4(M:Ptr,Count,Name,Compound).
 c_array_from_compound(:Ptr, +Compound)
Unify Ptr with an ffi blob c_ptr, which points to a C array containing all the arguments of the compount term Compound.

For now only numeric elements are supported.

Example

?- c_array_from_compound(Ptr,c(3,1,2)).
Ptr = <C long[3]>(0x561f248c6080).
 1588c_array_from_compound(M:Ptr, Compound) :-
 1589   nonvar(Compound),
 1590   !,
 1591   functor(Compound, _Name, Count),
 1592   c_array_from_compound(M:Ptr, Count, Compound).
 c_array_from_compound(:Ptr, +Count, +Compound)
Like c_array_from_compound/2 but produce a C array with only Count arguments from Compound.

For now only numeric elements are supported.

Example

?- c_array_from_compound(Ptr,2,c(3,1,2)).
Ptr = <C long[2]>(0x561f248a70c0).
 1608c_array_from_compound(_:Ptr, Count, Compound) :-
 1609   nonvar(Compound),
 1610   !,
 1611   compound_numeric(Compound,Typ),
 1612   c_sizeof(Typ, Size),
 1613   c_calloc(Ptr, Typ, Size, Count),
 1614   c_put_compound(Compound, Size, Ptr).
 1615
 1616
 1617% we only check the first argument,
 1618% and leave it to the user to make
 1619% sure all elements are of the same
 1620% type
 1621compound_numeric(Compound,long) :-
 1622   arg(1, Compound, H),
 1623   integer(H),
 1624   !.
 1625
 1626compound_numeric(Compound,double) :-
 1627   arg(1, Compound, H),
 1628   float(H),
 1629   !.
 1630
 1631
 1632		 /*******************************
 1633		 *             DICT		*
 1634		 *******************************/
 c_struct_dict(:Struct, ?Dict)
Translate between a struct and a dict
 1640c_struct_dict(M:Ptr, Dict) :-
 1641    nonvar(Ptr),
 1642    !,
 1643    c_typeof(Ptr, Type),
 1644    (   Type = struct(Name)
 1645    ->  findall(f(Field, Offset, FType),
 1646                c_current_struct_field(M:Name, Field, Offset, FType),
 1647                Fields),
 1648        maplist(get_field(Ptr), Fields, Pairs),
 1649        dict_pairs(Dict, Name, Pairs)
 1650    ;   domain_error(c_struct_pointer, Ptr)
 1651    ).
 1652
 1653get_field(Ptr, f(Name, Offset, Type), Name-Value) :-
 1654    c_load_(Ptr, Offset, Type, Value).
 1655
 1656
 1657		 /*******************************
 1658		 *            ENUM		*
 1659		 *******************************/
 c_current_enum(?Name, :Enum, ?Int)
True when Id is a member of Enum with Value.
 1665c_current_enum(Id, M:Enum, Value) :-
 1666    enum_module(M, '$c_enum'/3),
 1667    M:'$c_enum'(Id, Enum, Value).
 1668
 1669enum_module(M, PI) :-
 1670    nonvar(M),
 1671    !,
 1672    current_predicate(M:PI).
 1673enum_module(M, PI) :-
 1674    PI = Name/Arity,
 1675    functor(Head, Name, Arity),
 1676    current_module(M),
 1677    current_predicate(M:PI),
 1678    \+ predicate_property(M:Head, imported_from(_)).
 c_enum_in(+Name, :Enum, -Int) is det
Convert an input element for an enum name to an integer.
 1684c_enum_in(Id, Enum, Value) :-
 1685    c_current_enum(Id, Enum, Value),
 1686    !.
 1687c_enum_in(Id, Enum, _Value) :-
 1688    existence_error(enum_id, Id, Enum).
 c_enum_out(-Name, :Enum, +Int) is det
Convert an output element for an integer to an enum name.
 1694c_enum_out(Id, Enum, Value) :-
 1695    c_current_enum(Id, Enum, Value),
 1696    !.
 1697c_enum_out(_Id, Enum, Value) :-
 1698    existence_error(enum_value, Value, Enum).
 compile_enum(+Name, +Values)// is det
Compile an enum declaration into clauses for '$c_enum'/3.
 1704:- det(compile_enum//2). 1705compile_enum(Name, Values) -->
 1706    enum_clauses(Values, 0, Name).
 1707
 1708:- det(enum_clauses//3). 1709enum_clauses([], _, _) --> [].
 1710enum_clauses([enum_value(Id, -)|T], I, Name) -->
 1711    !,
 1712    [ '$c_enum'(Id, Name, I) ],
 1713    { I2 is I + 1 },
 1714    enum_clauses(T, I2, Name).
 1715enum_clauses([enum_value(Id, C)|T], _, Name) -->
 1716    { ast_constant(C, I) },
 1717    [ '$c_enum'(Id, Name, I) ],
 1718    { I2 is I + 1 },
 1719    enum_clauses(T, I2, Name).
 1720
 1721
 1722		 /*******************************
 1723		 *            TYPEDEF		*
 1724		 *******************************/
 c_current_typedef(:Name, :Type) is nondet
True when Name is a typedef name for Type.
 1730c_current_typedef(M:Name, M:Type) :-
 1731    enum_module(M, '$c_typedef'/2),
 1732    M:'$c_typedef'(Name, Type).
 1733
 1734compile_typedef(Name, Type) -->
 1735    [ '$c_typedef'(Name, Type) ].
 1736
 1737
 1738		 /*******************************
 1739		 *            MACROS		*
 1740		 *******************************/
 c_macro_expand(+T0, -T) is det
Perform macro expansion for T0 using rules for c_define/2
 1746c_macro_expand(T0, T) :-
 1747    prolog_load_context(module, M),
 1748    current_predicate(M:c_define/2), !,
 1749    c_expand(M, T0, T).
 1750c_macro_expand(T, T).
 1751
 1752c_expand(M, T0, T) :-
 1753    generalise(T0, T1),
 1754    M:c_define(T1, E),
 1755    T0 =@= T1,
 1756    !,
 1757    c_expand(M, E, T).
 1758c_expand(M, T0, T) :-
 1759    compound(T0),
 1760    compound_name_arguments(T0, Name, Args0),
 1761    maplist(c_expand(M), Args0, Args),
 1762    compound_name_arguments(T1, Name, Args),
 1763    T1 \== T0, !,
 1764    c_expand(M, T1, T).
 1765c_expand(_, T, T).
 1766
 1767generalise(T0, T) :-
 1768    compound(T0),
 1769    !,
 1770    compound_name_arity(T0, Name, Arity),
 1771    compound_name_arity(T, Name, Arity).
 1772generalise(T0, T) :-
 1773    atomic(T0),
 1774    !,
 1775    T = T0.
 1776generalise(_, _).
 1777
 1778
 1779		 /*******************************
 1780		 *        CPP CONSTANTS		*
 1781		 *******************************/
 1782
 1783add_constants(Module, Header0, Header) :-
 1784    current_predicate(Module:cpp_const/1),
 1785    findall(Const, Module:cpp_const(Const), Consts),
 1786    Consts \== [],
 1787    !,
 1788    must_be(list(atom), Consts),
 1789    maplist(const_decl, Consts, Decls),
 1790    atomics_to_string([Header0|Decls], "\n", Header).
 1791add_constants(_, Header, Header).
 1792
 1793const_decl(Const, Decl) :-
 1794    format(string(Decl), "static int __swipl_const_~w = ~w;", [Const, Const]).
 1795
 1796c_constants([]) --> [].
 1797c_constants([H|T]) --> c_constant(H), c_constants(T).
 1798
 1799c_constant(Name=AST) -->
 1800    { ast_constant(AST, Value) },
 1801    !,
 1802    [ cpp_const(Name, Value) ].
 1803c_constant(Name=AST) -->
 1804    { print_message(warning, c(not_a_constant(Name, AST))) }.
 1805
 1806
 1807		 /*******************************
 1808		 *           EXPANSION		*
 1809		 *******************************/
 1810
 1811cpp_expand(Modules, T0, CCallback) :-
 1812    nonvar(T0),
 1813    T0 = 'C'(sym(FName)),
 1814    member(M, Modules),
 1815    c_symbol_callback(M:FName, CCallback),
 1816    !.
 1817cpp_expand(Modules, T0, T) :-
 1818    atom(T0),
 1819    member(M, Modules),
 1820    current_predicate(M:cpp_const/2),
 1821    call(M:cpp_const(T0, T)),
 1822    !.
 1823cpp_expand(Modules0, T0, T) :-
 1824    nonvar(T0),
 1825    T0 = 'C'(Expr0),
 1826    nonvar(Expr0),
 1827    !,
 1828    cpp_expand_module(Expr0, Expr1, Modules0, Modules),
 1829    cpp_expand(Modules, Expr1, Expr),
 1830    cpp_eval(Expr, T).
 1831cpp_expand(Modules, T0, T) :-
 1832    compound(T0),
 1833    !,
 1834    compound_name_arguments(T0, Name, Args0),
 1835    maplist(cpp_expand(Modules), Args0, Args1),
 1836    compound_name_arguments(T1, Name, Args1),
 1837    (   T0 == T1
 1838    ->  T = T0
 1839    ;   T = T1
 1840    ).
 1841cpp_expand(_, T, T).
 1842
 1843cpp_expand_module(Expr0, Expr, Modules, [M|Modules]) :-
 1844    nonvar(Expr0),
 1845    Expr0 = _:_,
 1846    !,
 1847    strip_module(Expr0, M, Expr).
 1848cpp_expand_module(Expr, Expr, Modules, Modules).
 1849
 1850
 1851cpp_eval(Var, _) :-
 1852    var(Var),
 1853    !,
 1854    instantiation_error(Var).
 1855cpp_eval(Val0, Val) :-
 1856    atomic(Val0),
 1857    !,
 1858    Val = Val0.
 1859cpp_eval(Compound0, Val) :-
 1860    compound_name_arguments(Compound0, Name, Args0),
 1861    maplist(cpp_eval, Args0, Args),
 1862    compound_name_arguments(Compound, Name, Args),
 1863    cpp_eval_func(Compound, Val).
 1864
 1865cpp_eval_func((A|B), V)  :- !, V is A \/ B.
 1866cpp_eval_func(~(A), V)   :- !, V is \A.
 1867cpp_eval_func(&(A,B), V) :- !, V is A /\ B.
 1868cpp_eval_func(Term, V)   :-
 1869    current_arithmetic_function(Term),
 1870    !,
 1871    V is Term.
 1872
 1873
 1874system:term_expansion(T0, T) :-
 1875    prolog_load_context(module, M),
 1876    current_predicate(M:c_import/3),
 1877    cpp_expand([M], T0, T),
 1878    T0 \== T.
 1879
 1880		 /*******************************
 1881		 *        LOW LEVEL DOCS	*
 1882		 *******************************/
 c_calloc(-Ptr, +Type, +Size, +Count) is det
Allocate a chunk of memory similar to the C calloc() function. The chunk is associated with the created Ptr, a blob of type c_ptr (see blob/2). The content of the chunk is filled with 0-bytes. If the blob is garbage collected by the atom garbage collector the allocated chunk is freed.
Arguments:
Type- is the represented C type. It is either an atom or a term of the shape struct(Name), union(Name) or enum(Name). The atomic type name is not interpreted. See also c_typeof/2.
Size- is the size of a single element in bytes, i.e., should be set to sizeof(Type). As this low level function doesn't know how large a structure or union is, this figure must be supplied by the high level predicates.
Count- is the number of elements in the array.
 c_alloc_string(-Ptr, +Data, +Encoding) is det
Create a C char or wchar_t string from Prolog text Data. Data is an atom, string, code list, char list or integer. The text is encoded according to Encoding, which is one of iso_latin_1, utf8, octet, text or wchar_t. The encodings octet and iso_latin_1 are synonym. The conversion may raise a representation_error exception if the encoding cannot represent all code points in Data. The resulting string or wide string is nul-terminated. Note that Data may contain code point 0 (zero). The length of the string can be accessed using c_dim/3. The reported length includes the terminating nul code.

This predicate is normally accessed through the high level interface provided by c_alloc/2.

 c_free(+Ptr) is det
Free the chunk associated with Ptr by calling the registered release function immediately. This may be used to reduce the memory foodprint without waiting for the atom garbage collector. The blob itself can only be reclaimed by the atom garbage collector.

The type release function is non-NULL if the block as allocated using c_alloc/2 or a function was associated with a pointer created from an output argument or the foreign function return value using the ~(Type, Free) mechanism.

 c_disown(+Ptr) is det
Clear the release function associated with the blob. This implies that the block associated with the pointer is not released when the blob is garbage collected. This can be used to transfer ownership of a memory blob allocated using c_alloc/2 to the foreign application. The foreign application must call PL_free() from the SWI-Prolog API to release the memory. On systems where the heap is not associated with a foreign module, the C library free() function may be used as well. Using free() works on all Unix systems we are aware of, but does not work on Windows.
 c_load(+Ptr, +Offset, +Type, -Value) is det
Fetch a C arithmetic value of Type at Offset from the pointer. Value is unified with an integer or floating point number. If the size of the chunk behind the pointer is known, Offset is validated to be inside the chunk represented by Ptr. Pointers may
 c_load_string(+Ptr, -Data, +As, +Encoding) is det
 c_load_string(+Ptr, +Length, -Data, +As, +Encoding) is det
Assuming Ptr points at text, either char or wchar_t, extract the value to Prolog. The c_load_string/4 variant assumes the text is nul-terminated.
Arguments:
As- defines the resulting Prolog type and is one of atom, string, codes or chars
Encoding- is one of iso_latin_1, octet, utf8, text or wchar_t.
 c_offset(+Ptr0, +Offset, +Type, +Size, +Count, -Ptr) is det
Get a pointer to some location inside the chunk Ptr0. This is currently used to get a stand-alone pointer to a struct embedded in another struct or a struct from an array of structs. Note that this is not for accessing pointers inside a struct.

Creating a pointer inside an existing chunk increments the reference count of Ptr0. Reclaiming the two pointers requires two atom garbage collection cycles, one to reclaim the sub-pointer Ptr and one to reclaim Ptr0.

The c_offset/5 primitive can also be used to cast a pointer, i.e., reinterpret its contents as if the pointer points at data of a different type.

 c_store(+Ptr, +Offset, +Type, +Value) is det
Store a C scalar value of type Type at Offset into Ptr. If Value is a pointer, its reference count is incremented to ensure it is not garbage collected before Ptr is garbage collected.
 c_typeof(+Ptr, -Type) is det
True when Type is the Type used to create Ptr using c_calloc/4 or c_offset/6.
Arguments:
Type- is an atom or term of the shape struct(Name), union(Name) or enum(Name). Type may be mapped in zero or more *(Type) terms, representing the levels of pointer indirection.
 c_sizeof(+Type, -Bytes) is semidet
True when Bytes is the size of the C scalar type Type. Only supports basic C types. Fails silently on user defined types.
 c_alignof(+Type, -Bytes) is semidet
True when Bytes is the mininal alignment for the C scalar type Type. Only supports basic C types. Fails silently on user defined types. This value is used to compute the layout of structs.
 c_address(+Ptr, -Address) is det
True when Address is the (signed) integer address pointed at by Ptr.
 c_dim(+Ptr, -Count, -ElemSize) is det
True when Ptr holds Count elements of size ElemSize. Both Count and ElemSize are 0 (zero) if the value is not known.
 2012		 /*******************************
 2013		 *            MESSAGES		*
 2014		 *******************************/
 2015
 2016:- multifile
 2017    prolog:message//1,
 2018    prolog:error_message//1. 2019
 2020prolog:message(ffi(Msg)) -->
 2021    [ 'FFI: '-[] ],
 2022    message(Msg).
 2023prolog:error_message(ffi_error(Msg)) -->
 2024    [ 'FFI: '-[] ],
 2025    error_message(Msg).
 2026
 2027message(incompatible_return(Func, Prolog, C)) -->
 2028    [ '~p: incompatible return type: ~p <- ~p'-[Func, Prolog, C] ].
 2029message(incompatible_argument(Func, Prolog, C)) -->
 2030    [ '~p: incompatible parameter: ~p -> ~p'-[Func, Prolog, C] ].
 2031message(nonvoid_function(Func, Ret)) -->
 2032    [ '~p: return of "~w" is ignored'-[Func, Ret] ].
 2033message(void_function(Func, PlRet)) -->
 2034    [ '~p: void function defined to return ~p'-[Func, PlRet] ].
 2035message(nonmatching_params(Func, PlArgs, CArgs)) -->
 2036    [ '~p: non-matching parameter list: ~p -> ~p'-[Func, PlArgs, CArgs] ].
 2037
 2038error_message(define(QHead)) -->
 2039    ['Failed to create link-clause for ~p'-[QHead]]