View source with raw comments or as raw
    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)  2001-2014, University of Amsterdam, VU University Amsterdam
    7    All rights reserved.
    8
    9    Redistribution and use in source and binary forms, with or without
   10    modification, are permitted provided that the following conditions
   11    are met:
   12
   13    1. Redistributions of source code must retain the above copyright
   14       notice, this list of conditions and the following disclaimer.
   15
   16    2. Redistributions in binary form must reproduce the above copyright
   17       notice, this list of conditions and the following disclaimer in
   18       the documentation and/or other materials provided with the
   19       distribution.
   20
   21    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   22    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   23    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   24    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   25    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   26    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   27    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   28    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   29    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   31    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   32    POSSIBILITY OF SUCH DAMAGE.
   33*/
   34
   35:- module(qp_foreign,
   36          [ load_foreign_files/0,               %
   37            load_foreign_files/2,               % +Files, +Libs
   38            load_foreign_files/3,               % +Object, +Files, +Libs
   39            make_shared_object/3,               % +Object, +Files, +Libs
   40            make_foreign_wrapper_file/1,        % +OutBase
   41            make_foreign_wrapper_file/2,        % +OFiles, +OutBase
   42                                                % SICStus stuff
   43            make_foreign_resource_wrapper/3,    % +Resource, +ResBase, +FileBase
   44            load_foreign_resource/2             % +Resource, +Dir
   45          ]).   46
   47:- use_module(library(shlib)).   48:- use_module(library(gensym)).   49:- use_module(library(lists)).   50:- use_module(library(apply)).   51:- use_module(library(error)).

Quintus compatible foreign loader

This module defines a Quintus compatible foreign language interface based on the foreign_file/2 and foreign/3 declarations.

Predicates:

load_foreign_files
Load all foreign files defined with foreign_file/2 statement in the current module.
load_foreign_files(+Files, +Libs)
Load specified foreign files, linking them with the given libraries
load_foreign_files(+SharedObject, +Files, +Libs)
As load_foreign_files/2, but first tries to load `SharedObject'. If the SharedObject exists it is loaded using load_foreign_library/1. Otherwise it is first created with make_shared_object/3.
make_shared_object(+SharedObject, +Files, +Libs)
Generate a wrapper and link it using plld to the given SharedObject.
make_foreign_wrapper_file(+Files, +OutBase)
Generate wrapper for the named object files in OutBase.c.
make_foreign_wrapper_file(+Files)
Generate wrapper for all declared object files in OutBase.c.

Example:

foreign_file('-lm', [sin/2]).
foreign(sin, c, sin(+float, [-float])).
:- load_foreign_files,
   abolish(foreign_file, 2),
   abolish(foreign, 3).

Supported types:

SpecPrologC
integerintegerlong
floatfloat,integerdouble
singlefloat,integersingle
stringatom,stringchar *
atomatomatom identifier (type atomic)
NOTE This modules requires a correctly functioning swipl-ld and load_foreign_library/1 on your system. If this isn't the case use make_foreign_wrapper_file/[1,2] to generate a wrapper and use static embedding.
bug
- Only supports C-interface
- Insufficient checking for misusage.
- Documentation is too short and very outdated */
  111:- module_transparent
  112    load_foreign_files/0.  113
  114:- meta_predicate
  115    load_foreign_files(:, +),
  116    load_foreign_files(+, :, +),
  117    make_shared_object(+, :, +),
  118    make_foreign_wrapper_file(:),
  119    make_foreign_wrapper_file(:, +),
  120                                    % SICStus
  121    make_foreign_resource_wrapper(:, +, +),
  122    load_foreign_resource(:, +).  123
  124setting(linker, 'swipl-ld').
  125
  126hook(M:Goal) :-
  127    M:Goal.
 make_wrappers(+PrologHeads, +Module, +OutStream)
  131make_wrappers([], _, _).
  132make_wrappers([H|T], M, Out) :-
  133    make_wrapper(Out, M:H),
  134    make_wrappers(T, M, Out).
 make_wrapper(+Stream, :PrologHead)
Generates a C-wrapper function for the given foreign defined Prolog predicate. The wrapper is called _plw_<predname><arity>.
  141make_wrapper(Out, Spec) :-
  142    get_foreign_head(Spec, Func, Head),
  143    !,
  144    (   check_head(Head)
  145    ->  wrapper_name(Head, WrapName, ArgN),
  146        make_C_header(Out, WrapName, ArgN),
  147        make_C_decls(Out, Head),
  148        make_C_prototype(Out, Head),
  149        make_C_input_conversions(Out, Head),
  150        make_C_wrapper_setup(Out),
  151        make_C_call(Out, Head, Func),
  152        make_C_wrapper_check(Out),
  153        make_C_output_conversions(Out, Head),
  154        make_C_footer(Out)
  155    ;   fail
  156    ).
  157make_wrapper(_, Spec) :-
  158    existence_error(foreign_declaration, Spec).
 get_foreign_head(:Spec, -Func, -Head)
Get 3rd argument of relevant foreign/3 clause. Seems there are two versions. In Quintus Spec was a predicate specification and in SICStus it seems to be a (C) function name.
  166get_foreign_head(M:Function, Function, M:Head) :-
  167    prolog_load_context(dialect, sicstus),
  168    !,
  169    hook(M:foreign(Function, c, Head)).
  170get_foreign_head(M:Spec, Func, M:Head) :-
  171    (   atom(Spec),
  172        hook(M:foreign(Spec, c, Head)),
  173        functor(Head, Spec, _)
  174    ->  true
  175    ;   Spec = Name/Arity
  176    ->  functor(Head, Name, Arity),
  177        hook(M:foreign(Func, c, Head))
  178    ;   Head = Spec,
  179        hook(M:foreign(Func, c, Head))
  180    ).
  181
  182
  183check_head(_:Head) :-
  184    functor(Head, _, Arity),
  185    (   Arity == 0
  186    ->  true
  187    ;   arg(_, Head, [-T]),
  188        \+ valid_type(T)
  189    ->  warning('Bad return type ~w in ~w', [T, Head]),
  190        fail
  191    ;   arg(N, Head, [-_T]),
  192        N \== Arity
  193    ->  warning('Return type must be last in ~w', Head),
  194        fail
  195    ;   (arg(_, Head, -T) ; arg(_, Head, +T)),
  196        \+ valid_type(T)
  197    ->  warning('Bad type ~w in ~w', [T, Head]),
  198        fail
  199    ;   true
  200    ).
  201
  202valid_type(int).
  203valid_type(integer).
  204valid_type(size_t).
  205valid_type(float).
  206valid_type(single).
  207valid_type(string).
  208valid_type(chars).                      % actually, `codes'!
  209valid_type(atom).
  210valid_type(term).
  211valid_type(address).
  212valid_type(address(_)).
 cvt_name(+Type, +IO, -Suffix) is det
  216cvt_name(chars,      _, codes) :- !.
  217cvt_name(address(_), _, address) :- !.
  218cvt_name(int,        o, int64) :- !.
  219cvt_name(integer,    o, int64) :- !.
  220cvt_name(size_t,     o, int64) :- !.
  221cvt_name(integer,    i, long) :- !.
  222cvt_name(Type,       _, Type).
 make_C_header(+Stream, +WrapperName, +Arity)
Write function-header for the wrapper. This is easy as the the return-type is always foreign_t and the arguments are always of type `term_t'. The arguments are simply named `a', `b', ...
  232make_C_header(Out, WrapName, ArgN) :-
  233    format(Out, '~n~nstatic foreign_t~n~w(', [WrapName]),
  234    forall(between(1, ArgN, A),
  235           (   (A \== 1 -> format(Out, ', ', []) ; true)
  236           ,   arg_name(A, AName),
  237               format(Out, 'term_t ~w', [AName])
  238           )),
  239    format(Out, ')~n{ ', []).
 make_C_decls(+Stream, :PrologHead)
Writes the C variable declarations. If the return value is used a variable named `rval' is created. For each input parameter a C variable named i<argname> is created; for each output variable o<argname>.
  248make_C_decls(Out, _:Head) :-
  249    compound(Head),
  250    arg(_, Head, [-PlType]),
  251    map_C_type(PlType, CType),
  252    format(Out, '~wrval;~n  ', [CType]),
  253    fail.
  254make_C_decls(Out, _:Head) :-
  255    compound(Head),
  256    arg(N, Head, -PlType),
  257    arg_name(N, AName),
  258    (   PlType == term
  259    ->  format(Out, 'term_t o_~w = PL_new_term_ref();~n  ', [AName])
  260    ;   map_C_type(PlType, CType),
  261        format(Out, '~wo_~w;~n  ', [CType, AName])
  262    ),
  263    fail.
  264make_C_decls(Out, _:Head) :-
  265    compound(Head),
  266    arg(N, Head, +PlType),
  267    PlType \== term,
  268    map_C_type(PlType, CType),
  269    CType \== term,
  270    arg_name(N, AName),
  271    format(Out, '~wi_~w;~n  ', [CType, AName]),
  272    fail.
  273make_C_decls(Out, _) :-
  274    format(Out, '~n', []).
 make_C_prototype(+Stream, :PrologHead)
If the function handles floats or doubles, make a prototype declaration for it to avoid unwanted conversions.
  281make_C_prototype(Out, M:Head) :-
  282    (   compound(Head),
  283        arg(_, Head, [-Type])
  284    ->  map_C_type(Type, CType)
  285    ;   CType = 'void '
  286    ),
  287    copy_term(Head, H2),            % don't bind Head
  288    hook(M:foreign(CFunc, c, H2)),
  289    !,
  290    format(Out, '  extern ~w~w(', [CType, CFunc]),
  291    (   compound(Head),
  292        arg(N, Head, AType),
  293        AType \= [_],               % return-type
  294        (N > 1 -> format(Out, ', ', []) ; true),
  295        (   AType = +T2
  296        ->  map_C_type(T2, CT2),
  297            format(Out, '~w', [CT2])
  298        ;   AType == -term
  299        ->  format(Out, term_t, [])
  300        ;   AType = -T2
  301        ->  map_C_type(T2, CT2),
  302            format(Out, '~w *', [CT2])
  303        ),
  304        fail
  305    ;   format(Out, ');~n~n', [])
  306    ).
  307make_C_prototype(_, _).
 make_C_input_conversions(+Stream, :PrologHead)
Generate the input checking and conversion code. Assumes boolean functions that take a Prolog term_t as first argument and a pointer to the requested C-type as a second argument. Function returns 0 if the conversion fails.
  317make_C_input_conversions(Out, _:Head) :-
  318    findall(N-T, (compound(Head),arg(N, Head, +T)), IArgs0),
  319    exclude(term_arg, IArgs0, IArgs),
  320    (   IArgs == []
  321    ->  true
  322    ;   format(Out, '  if ( ', []),
  323        (   member(N-T, IArgs),
  324            T \== term,
  325            (IArgs \= [N-T|_] -> format(Out, ' ||~n       ', []) ; true),
  326            arg_name(N, AName),
  327            atom_concat(i_, AName, IName),
  328            cvt_name(T, i, CVT),
  329            format(Out, '!PL_cvt_i_~w(~w, &~w)', [CVT, AName, IName]),
  330            fail
  331        ;   true
  332        ),
  333        format(Out, ' )~n    return FALSE;~n~n', [])
  334    ).
  335
  336term_arg(_-term).
 make_C_call(+Stream, :PrologHead, +CFunction)
Generate the actual call to the foreign function. Input variables may be handed directly; output variables as a pointer to the o<var>, except for output-variables of type term.
  345make_C_call(Out, _:Head, CFunc) :-
  346    (   compound(Head),
  347        arg(_, Head, [-_])
  348    ->  format(Out, '  rval = ~w(', [CFunc])
  349    ;   format(Out, '  (void) ~w(', [CFunc])
  350    ),
  351    compound(Head),
  352    arg(N, Head, Arg),
  353    Arg \= [_],
  354    (N \== 1 -> format(Out, ', ', []) ; true),
  355    arg_name(N, AName),
  356    (   Arg = -term
  357    ->  format(Out, 'o_~w', [AName])
  358    ;   Arg = -_
  359    ->  format(Out, '&o_~w', [AName])
  360    ;   Arg = +term
  361    ->  format(Out, '~w', [AName])
  362    ;   format(Out, 'i_~w', [AName])
  363    ),
  364    fail.
  365make_C_call(Out, _, _) :-
  366    format(Out, ');~n', []).
 make_C_wrapper_setup(+Stream)
Call SP_WRAP_INIT() when running on SICStus. This supports SP_fail() and SP_raise_exception().
  373make_C_wrapper_setup(Stream) :-
  374    prolog_load_context(dialect, sicstus),
  375    !,
  376    format(Stream, '  SP_WRAP_INIT();~n', []).
  377make_C_wrapper_setup(_).
 make_C_wrapper_check(+Stream)
Call SP_WRAP_CHECK_STATE() when running on SICStus. This supports SP_fail() and SP_raise_exception().
  385make_C_wrapper_check(Stream) :-
  386    prolog_load_context(dialect, sicstus),
  387    !,
  388    format(Stream, '  SP_WRAP_CHECK_STATE();~n', []).
  389make_C_wrapper_check(_).
 make_C_output_conversions(+Stream, :PrologHead)
Generate conversions for the output arguments and unify them with the Prolog term_t arguments.
  397make_C_output_conversions(Out, _:Head) :-
  398    findall(N-T, (compound(Head),arg(N, Head, -T)), OArgs0),
  399    (   compound(Head),
  400        arg(_, Head, [-RT])
  401    ->  OArgs = [rval-RT|OArgs0]
  402    ;   OArgs = OArgs0
  403    ),
  404    (   OArgs == []
  405    ->  true
  406    ;   format(Out, '~n  if ( ', []),
  407        (   member(N-T, OArgs),
  408            (   N == rval
  409            ->  OName = rval,
  410                arg(RN, Head, [-_]),
  411                arg_name(RN, AName)
  412            ;   arg_name(N, AName),
  413                atom_concat(o_, AName, OName)
  414            ),
  415            (OArgs = [N-T|_] -> true ; format(Out, ' ||~n       ', [])),
  416            (   T == term
  417            ->  format(Out, '!PL_unify(~w, ~w)', [OName, AName])
  418            ;   cvt_name(T, o, CVT),
  419                format(Out, '!PL_cvt_o_~w(~w, ~w)', [CVT, OName, AName])
  420            ),
  421            fail
  422        ;   true
  423        ),
  424        format(Out, ' )~n    return FALSE;~n', [])
  425    ).
  426
  427
  428make_C_footer(Out) :-
  429    format(Out, '~n  return TRUE;~n}~n', []).
  430
  431                 /*******************************
  432                 *        INIT STATEMENT        *
  433                 *******************************/
 make_C_init(+Stream, +InstallFunc, +InitFunc, +Module, +PredList)
Generate an array of PL_extension structures, that may be used to create a statically linked image as well as through the PL_load_extensions() call.

Of the supported PL_FA_<FLAGS>, TRANSPARENT may be declared by looking at the transparent (meta_predivate) attribute of the predicate.

  445make_C_init(Out, InstallFunc, Init, M, Preds) :-
  446    format(Out, '~n~nstatic PL_extension predicates [] =~n{~n', []),
  447    format(Out, '/*{ "name", arity, function, PL_FA_<flags> },*/~n', []),
  448    (   member(Pred, Preds),
  449        get_foreign_head(M:Pred, _Func, Head),
  450        Head = M:H,
  451        functor(H, Name, Arity),
  452        wrapper_name(Head, Wrapper, Arity),
  453        foreign_attributes(M:H, Atts),
  454        format(Out, '  { "~w", ~d, ~w, ~w },~n',
  455               [Name, Arity, Wrapper, Atts]),
  456        fail
  457    ;   true
  458    ),
  459    format(Out, '  { NULL, 0, NULL, 0 } /* terminator */~n};~n~n', []),
  460    format(Out, 'install_t~n~w()~n{ PL_load_extensions(predicates);~n',
  461           [InstallFunc]),
  462    sicstus_init_function(Out, Init),
  463    format(Out, '}~n', []).
  464
  465sicstus_init_function(_, -) :- !.
  466sicstus_init_function(Out, Init) :-
  467    format(Out, '  extern void ~w(int);~n', [Init]),
  468    format(Out, '  ~w(0);~n', [Init]).
  469
  470foreign_attributes(Head, Atts) :-
  471    findall(A, foreign_attribute(Head, A), A0),
  472    (   A0 == []
  473    ->  Atts = 0
  474    ;   atomic_list_concat(A0, '|', Atts)
  475    ).
  476
  477foreign_attribute(Head, 'PL_FA_TRANSPARENT') :-
  478    predicate_property(Head, transparent).
 make_C_deinit(+Stream, +UninstallFunc, +DeInitFunc) is det
Write the uninstall function
  484make_C_deinit(_, _, -) :- !.
  485make_C_deinit(Out, Func, DeInit) :-
  486    format(Out, '~ninstall_t~n', []),
  487    format(Out, '~w()~n', [Func]),
  488    format(Out, '{ extern void ~w(int);~n', [DeInit]),
  489    format(Out, '  ~w(0);~n', [DeInit]),
  490    format(Out, '}~n', []).
 make_C_file_header(+Stream)
Output the generic header declarations needed and some comments
  497make_C_file_header(Out) :-
  498    current_prolog_flag(version_data, swi(Major, Minor, Patch, _)),
  499    get_time(Time),
  500    format_time(string(When), '%F %H:%M', Time),
  501    format(Out, '/*  SWI-Prolog link wrapper~n', []),
  502    format(Out, '    Generated by SWI-Prolog version ~w.~w.~w~n',
  503           [Major, Minor, Patch]),
  504    format(Out, '    At ~s~n', [When]),
  505    (   source_location(File, Line)
  506    ->  format(Out, '    Source context ~w:~d~n', [File, Line])
  507    ;   true
  508    ),
  509    format(Out, '*/~n~n', []),
  510    format(Out, '#include <SWI-Prolog.h>~n', []),
  511    make_C_compat_file_header(Out),
  512    format(Out, '#ifndef NULL~n', []),
  513    format(Out, '#define NULL ((void *)0)~n', []),
  514    format(Out, '#endif~n~n', []).
  515
  516
  517make_C_compat_file_header(Out) :-
  518    prolog_load_context(dialect, sicstus),
  519    !,
  520    format(Out, '#define SP_WRAPPER 1~n', []),
  521    format(Out, '#include <sicstus/sicstus.h>~n', []).
  522make_C_compat_file_header(_).
  523
  524
  525                 /*******************************
  526                 *           TOPLEVEL           *
  527                 *******************************/
 load_foreign_files is det
 load_foreign_files(:Files, +Libs) is det
 load_foreign_files(+SharedObject, :Files, +Libs) is det
Calls make_foreign_wrapper_file(+File), compiles the wrapper and loads the predicates.
  536load_foreign_files :-
  537    context_module(M),
  538    findall(File, hook(M:foreign_file(File, _)), OFiles),
  539    load_foreign_files(M:OFiles, []).
  540load_foreign_files(OFiles, Libs) :-
  541    gensym(link, LinkBase),
  542    load_foreign_files(LinkBase, OFiles, Libs).
  543
  544load_foreign_files(LinkBase, M:_, _) :-
  545    catch(load_foreign_library(M:LinkBase), _, fail),
  546    !.
  547load_foreign_files(LinkBase, OFiles, Libs) :-
  548    make_shared_object(LinkBase, OFiles, Libs),
  549    OFiles = M:_List,
  550    load_foreign_library(M:LinkBase).
 make_shared_object(+Object, :Files, +Libs) is det
Generate a wrapper and link it using plld to the given SharedObject.
  557make_shared_object(LinkBase, M:OFiles, Libs) :-
  558    make_foreign_wrapper_file(M:OFiles, LinkBase),
  559    file_name_extension(LinkBase, c, CFile),
  560    build_shared_object(LinkBase, [CFile|OFiles], Libs).
 make_foreign_wrapper_file(:OutFile) is det
 make_foreign_wrapper_file(:Files, +OutFile) is det
Just output the wrapper file to the named .c file. May be used to prepare for static linking or the preparation of the native SWI-Prolog foreign-file.
  569make_foreign_wrapper_file(M:CFile) :-
  570    findall(File, hook(M:foreign_file(File, _)), OFiles),
  571    make_foreign_wrapper_file(M:OFiles, CFile).
  572make_foreign_wrapper_file(M:OFiles, Base) :-
  573    file_name_extension(Base, c, CFile),
  574    file_base_name(Base, FuncBase),
  575    atom_concat(install_, FuncBase, InstallFunc),
  576    collect_foreign_predicates(OFiles, M, Preds),
  577    open(CFile, write, Out),
  578    make_C_file_header(Out),
  579    make_wrappers(Preds, M, Out),
  580    make_C_init(Out, InstallFunc, -, M, Preds),
  581    close(Out).
  582
  583
  584collect_foreign_predicates([], _, []).
  585collect_foreign_predicates([File|Files], M, Preds) :-
  586    hook(M:foreign_file(File, P0)),
  587    collect_foreign_predicates(Files, M, P1),
  588    append(P0, P1, Preds).
  589
  590build_shared_object(Object, Files, Libs) :-
  591    current_prolog_flag(shared_object_extension, Ext),
  592    file_name_extension(Object, Ext, SharedObject),
  593    append(Files, Libs, Input),
  594    atomic_list_concat(Input, ' ', InputAtom),
  595    setting(linker, Linker),
  596    format(string(Command),
  597           '~w -shared -o ~w ~w', [Linker, SharedObject, InputAtom]),
  598    shell(Command).
  599
  600
  601                 /*******************************
  602                 *            SICSTUS           *
  603                 *******************************/
 make_foreign_resource_wrapper(:Resource, +ResBase, +FileBase)
Create a wrapper-file for the given foreign resource
  609make_foreign_resource_wrapper(M:Resource, ResBase, FileBase) :-
  610    hook(M:foreign_resource(Resource, Functions)),
  611    take(init(Init), Functions, Functions1, -),
  612    take(deinit(DeInit), Functions1, Preds, -),
  613    file_name_extension(FileBase, c, CFile),
  614    file_base_name(ResBase, FuncBase),
  615    atom_concat(install_, FuncBase, InstallFunc),
  616    atom_concat(uninstall_, FuncBase, UninstallFunc),
  617    open(CFile, write, Out),
  618    make_C_file_header(Out),
  619    make_wrappers(Preds, M, Out),
  620    make_C_init(Out, InstallFunc, Init, M, Preds),
  621    make_C_deinit(Out, UninstallFunc, DeInit),
  622    close(Out).
  623
  624take(Term, List, Rest, Default) :-
  625    (   select(Term, List, Rest)
  626    ->  true
  627    ;   arg(1, Term, Default),
  628        Rest = List
  629    ).
 load_foreign_resource(:Resource, +Dir)
Load a foreign module. First try to load from the same direcory as the Prolog file. Otherwise load using SWI-Prolog's default search path.
  638load_foreign_resource(M:Resource, Source) :-
  639    absolute_file_name(Resource, Object,
  640                       [ file_type(executable),
  641                         relative_to(Source),
  642                         file_errors(fail)
  643                       ]),
  644    !,
  645    load_foreign_library(M:Object).
  646load_foreign_resource(M:Resource, _) :-
  647    load_foreign_library(M:foreign(Resource)).
  648
  649
  650                 /*******************************
  651                 *             UTIL             *
  652                 *******************************/
  653
  654arg_name(N, Name) :-
  655    C is N + 0'a - 1,
  656    atom_codes(Name, [C]).
  657
  658wrapper_name(_:Head, Wrapper, Arity) :-
  659    functor(Head, Name, Arity),
  660    atomic_list_concat(['_plw_', Name, Arity], Wrapper).
 map_C_type(+Prolog, -C)
Map Prolog interface type declarations into C types.
  666map_C_type(X, Y) :-
  667    map_C_type_(X, Y),
  668    !.
  669map_C_type(X, X).
  670
  671map_C_type_(int, 'int ').
  672map_C_type_(integer, 'long ').
  673map_C_type_(size_t, 'size_t ').
  674map_C_type_(float,   'double ').
  675map_C_type_(string,  'char *').
  676map_C_type_(chars,   'char *').
  677map_C_type_(address, 'void *').
  678map_C_type_(address(Of), Type) :-
  679    atom_concat(Of, ' *', Type).
  680map_C_type_(term,    'term_t ').
  681
  682warning(Fmt, Args) :-
  683    print_message(warning, format(Fmt, Args)).
  684
  685
  686                 /*******************************
  687                 *            XREF              *
  688                 *******************************/
  689
  690:- multifile
  691    prolog:hook/1.  692
  693prolog:hook(foreign(_,_,_)).
  694prolog:hook(foreign_resource(_,_))