2001-04-09 20:54:03 +01:00
/*************************************************************************
* *
* YAP Prolog *
* *
* Yap Prolog was developed at NCCUP - Universidade do Porto *
* *
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
* *
**************************************************************************
* *
* File: load_foreign.yap *
* Last rev: 8/2/88 *
* mods: *
* comments: Utility predicates for load_foreign *
* *
*************************************************************************/
2014-09-11 20:06:57 +01:00
2014-04-09 12:39:29 +01:00
:- system_module( '$_load_foreign', [load_foreign_files/3,
open_shared_object/2,
open_shared_object/3], ['$import_foreign'/3]).
:- use_system_module( '$_errors', ['$do_error'/2]).
:- use_system_module( '$_modules', ['$do_import'/3]).
2016-01-20 22:36:16 +00:00
/**
@defgroup LoadForeign Access to Foreign Language Programs
@ingroup fli
@{
2014-12-24 15:32:29 +00:00
*/
2014-09-11 20:06:57 +01:00
/** @pred load_foreign_files( _Files_, _Libs_, _InitRoutine_)
should be used, from inside YAP, to load object files produced by the C
compiler. The argument _ObjectFiles_ should be a list of atoms
specifying the object files to load, _Libs_ is a list (possibly
empty) of libraries to be passed to the unix loader (`ld`) and
InitRoutine is the name of the C routine (to be called after the files
are loaded) to perform the necessary declarations to YAP of the
2016-04-12 16:22:53 +01:00
predicates defined in the files.
2014-09-11 20:06:57 +01:00
YAP will search for _ObjectFiles_ in the current directory first. If
it cannot find them it will search for the files using the environment
variable:
+ YAPLIBDIR
if defined, or in the default library.
2016-02-11 14:17:30 +00:00
YAP supports the SWI-Prolog interface to loading foreign code, the shlib package.
2014-09-11 20:06:57 +01:00
*/
2001-04-09 20:54:03 +01:00
load_foreign_files(Objs,Libs,Entry) :-
2016-01-03 02:06:09 +00:00
source_module(M),
2014-09-22 18:13:35 +01:00
'$check_objs_for_load_foreign_files'(Objs,NewObjs,load_foreign_files(Objs,Libs,Entry)),
'$check_libs_for_load_foreign_files'(Libs,NewLibs,load_foreign_files(Objs,Libs,Entry)),
'$check_entry_for_load_foreign_files'(Entry,load_foreign_files(Objs,Libs,Entry)),
2016-04-12 16:22:53 +01:00
(
2014-10-10 12:52:03 +01:00
recordzifnot( '$foreign', M:'$foreign'(Objs,Libs,Entry), _)
->
'$load_foreign_files'(NewObjs,NewLibs,Entry),
(
2016-02-11 14:17:30 +00:00
prolog_load_context(file, F)
->
ignore( recordzifnot( '$load_foreign_done', [F, M], _) )
;
true
)
;
2016-04-12 16:22:53 +01:00
true
2016-02-11 14:17:30 +00:00
),
2016-04-12 16:22:53 +01:00
!.
2016-02-11 14:17:30 +00:00
/** @pred load_absolute_foreign_files( _Files_, _Libs_, _InitRoutine_)
Loads object files produced by the C compiler. It is useful when no search should be performed and instead one has the full paths to the _Files_ and _Libs_.
*/
load_absolute_foreign_files(Objs,Libs,Entry) :-
source_module(M),
2016-04-12 16:22:53 +01:00
(
2016-02-11 14:17:30 +00:00
recordzifnot( '$foreign', M:'$foreign'(Objs,Libs,Entry), _)
->
'$load_foreign_files'(Objs,Libs,Entry),
(
2014-10-10 12:52:03 +01:00
prolog_load_context(file, F)
2014-09-22 18:13:35 +01:00
->
2014-10-02 14:40:45 +01:00
ignore( recordzifnot( '$load_foreign_done', [F, M], _) )
;
2014-10-10 12:52:03 +01:00
true
)
;
2016-04-12 16:22:53 +01:00
true
2014-10-10 12:52:03 +01:00
),
!.
2001-04-09 20:54:03 +01:00
'$check_objs_for_load_foreign_files'(V,_,G) :- var(V), !,
2002-09-09 18:40:12 +01:00
'$do_error'(instantiation_error,G).
2001-04-09 20:54:03 +01:00
'$check_objs_for_load_foreign_files'([],[],_) :- !.
'$check_objs_for_load_foreign_files'([Obj|Objs],[NObj|NewObjs],G) :- !,
'$check_obj_for_load_foreign_files'(Obj,NObj,G),
'$check_objs_for_load_foreign_files'(Objs,NewObjs,G).
'$check_objs_for_load_foreign_files'(Objs,_,G) :-
2002-09-09 18:40:12 +01:00
'$do_error'(type_error(list,Objs),G).
2001-04-09 20:54:03 +01:00
'$check_obj_for_load_foreign_files'(V,_,G) :- var(V), !,
2002-09-09 18:40:12 +01:00
'$do_error'(instantiation_error,G).
2001-04-09 20:54:03 +01:00
'$check_obj_for_load_foreign_files'(Obj,NewObj,_) :- atom(Obj), !,
2014-03-04 11:58:48 +00:00
( atom(Obj), Obj1 = foreign(Obj) ; Obj1 = Obj ),
absolute_file_name(foreign(Obj),[file_type(executable),
access(read),
expand(true),
file_errors(fail)
], NewObj).
2001-04-09 20:54:03 +01:00
'$check_obj_for_load_foreign_files'(Obj,_,G) :-
2002-09-09 18:40:12 +01:00
'$do_error'(type_error(atom,Obj),G).
2001-04-09 20:54:03 +01:00
2007-05-24 20:54:45 +01:00
'$check_libs_for_load_foreign_files'(V,_,G) :- var(V), !,
2002-09-09 18:40:12 +01:00
'$do_error'(instantiation_error,G).
2007-05-24 20:54:45 +01:00
'$check_libs_for_load_foreign_files'([],[],_) :- !.
'$check_libs_for_load_foreign_files'([Lib|Libs],[NLib|NLibs],G) :- !,
'$check_lib_for_load_foreign_files'(Lib,NLib,G),
'$check_libs_for_load_foreign_files'(Libs,NLibs,G).
'$check_libs_for_load_foreign_files'(Libs,_,G) :-
2002-09-09 18:40:12 +01:00
'$do_error'(type_error(list,Libs),G).
2001-04-09 20:54:03 +01:00
2007-05-24 20:54:45 +01:00
'$check_lib_for_load_foreign_files'(V,_,G) :- var(V), !,
2002-09-09 18:40:12 +01:00
'$do_error'(instantiation_error,G).
2007-05-24 20:54:45 +01:00
'$check_lib_for_load_foreign_files'(Lib,NLib,_) :- atom(Lib), !,
2013-11-15 16:04:14 +00:00
'$process_obj_suffix'(Lib,NewLib),
'$checklib_prefix'(NewLib,NLib).
2007-05-24 20:54:45 +01:00
'$check_lib_for_load_foreign_files'(Lib,_,G) :-
2002-09-09 18:40:12 +01:00
'$do_error'(type_error(atom,Lib),G).
2001-04-09 20:54:03 +01:00
2013-11-15 16:04:14 +00:00
'$process_obj_suffix'(Obj,Obj) :-
2015-06-19 01:12:05 +01:00
current_prolog_flag(shared_object_extension, ObjSuffix),
2013-11-15 16:04:14 +00:00
sub_atom(Obj, _, _, 0, ObjSuffix), !.
'$process_obj_suffix'(Obj,NewObj) :-
2015-06-19 01:12:05 +01:00
current_prolog_flag(shared_object_extension, ObjSuffix),
2013-11-15 16:04:14 +00:00
atom_concat([Obj,'.',ObjSuffix],NewObj).
2007-05-24 20:54:45 +01:00
2013-11-15 16:04:14 +00:00
'$checklib_prefix'(F,F) :- is_absolute_file_name(F), !.
'$checklib_prefix'(F, F) :-
sub_atom(F, 0, _, _, lib), !.
'$checklib_prefix'(F, Lib) :-
atom_concat(lib, F, Lib).
2007-05-24 20:54:45 +01:00
2014-02-09 18:06:37 +00:00
'$import_foreign'(F, M0, M) :-
M \= M0,
predicate_property(M0:P,built_in),
predicate_property(M0:P,file(F)),
functor(P, N, K),
'$do_import'(N/K-N/K, M0, M),
fail.
'$import_foreign'(_F, _M0, _M).
2007-05-24 20:54:45 +01:00
2001-04-09 20:54:03 +01:00
'$check_entry_for_load_foreign_files'(V,G) :- var(V), !,
2002-09-09 18:40:12 +01:00
'$do_error'(instantiation_error,G).
2001-04-09 20:54:03 +01:00
'$check_entry_for_load_foreign_files'(Entry,_) :- atom(Entry), !.
'$check_entry_for_load_foreign_files'(Entry,G) :-
2002-09-09 18:40:12 +01:00
'$do_error'(type_error(atom,Entry),G).
2001-04-09 20:54:03 +01:00
2014-09-11 20:06:57 +01:00
/** @pred open_shared_object(+ _File_, - _Handle_)
File is the name of a shared object file (called dynamic load
library in MS-Windows). This file is attached to the current process
and _Handle_ is unified with a handle to the library. Equivalent to
`open_shared_object(File, [], Handle)`. See also
load_foreign_library/1 and `load_foreign_library/2`.
On errors, an exception `shared_object`( _Action_,
_Message_) is raised. _Message_ is the return value from
dlerror().
2016-04-12 16:22:53 +01:00
2014-09-11 20:06:57 +01:00
*/
2010-06-17 00:29:01 +01:00
open_shared_object(File, Handle) :-
2014-09-22 18:13:35 +01:00
open_shared_object(File, [], Handle).
2001-04-09 20:54:03 +01:00
2014-09-11 20:06:57 +01:00
/** @pred open_shared_object(+ _File_, - _Handle_, + _Options_)
As `open_shared_object/2`, but allows for additional flags to
be passed. _Options_ is a list of atoms. `now` implies the
2016-04-12 16:22:53 +01:00
symbols are
2014-09-11 20:06:57 +01:00
resolved immediately rather than lazily (default). `global` implies
symbols of the loaded object are visible while loading other shared
objects (by default they are local). Note that these flags may not
be supported by your operating system. Check the documentation of
`dlopen()` or equivalent on your operating system. Unsupported
2016-04-12 16:22:53 +01:00
flags are silently ignored.
2014-09-11 20:06:57 +01:00
*/
2010-06-17 00:29:01 +01:00
open_shared_object(File, Opts, Handle) :-
'$open_shared_opts'(Opts, open_shared_object(File, Opts, Handle), OptsI),
2014-09-22 18:13:35 +01:00
'$open_shared_object'(File, OptsI, Handle),
prolog_load_context(module, M),
ignore( recordzifnot( '$foreign', M:'$swi_foreign'(File,Opts, Handle), _) ).
2001-04-09 20:54:03 +01:00
2014-10-07 01:35:41 +01:00
'$open_shared_opts'(Opts, G, _OptsI) :-
2010-06-17 00:29:01 +01:00
var(Opts), !,
'$do_error'(instantiation_error,G).
'$open_shared_opts'([], _, 0) :- !.
2013-11-11 10:28:45 +00:00
'$open_shared_opts'([Opt|Opts], G, V) :-
2010-06-17 00:29:01 +01:00
'$open_shared_opts'(Opts, G, V0),
'$open_shared_opt'(Opt, G, OptV),
V0 is V \/ OptV.
2016-04-12 16:22:53 +01:00
2010-06-17 00:29:01 +01:00
'$open_shared_opt'(Opt, G, _) :-
var(Opt), !,
'$do_error'(instantiation_error,G).
'$open_shared_opt'(now, __, 1) :- !.
'$open_shared_opt'(global, __, 2) :- !.
'$open_shared_opt'(Opt, Goal, _) :-
'$do_error'(domain_error(open_shared_object_option,Opt),Goal).
2016-04-12 16:22:53 +01:00
2014-09-22 18:13:35 +01:00
/** @pred call_shared_object_function(+ _Handle_, + _Function_)
2014-09-15 19:10:49 +01:00
2014-09-22 18:13:35 +01:00
Call the named function in the loaded shared library. The function is
called without arguments and the return-value is ignored. YAP supports
installing foreign language predicates using calls to 'UserCCall()`,
`PL_register_foreign()`, and friends.
2014-09-15 19:10:49 +01:00
*/
2014-09-22 18:13:35 +01:00
call_shared_object_function( Handle, Function) :-
'$call_shared_object_function'( Handle, Function),
prolog_load_context(module, M),
ignore( recordzifnot( '$foreign', M:'$swi_foreign'( Handle, Function ), _) ).
2016-01-20 22:36:16 +00:00
%% @}
2014-09-15 19:10:49 +01:00
2016-04-12 16:22:53 +01:00
/** @pred $slave is det
Called at boot-time when Prolog is run from another language (eg, Java, Python, Android)
*/
'$slave' :-
getenv( '__PYVENV_LAUNCHER__', _ ),
use_module( library(python) ).