Foreign modules may be linked to Prolog in two ways. Using
static linking, the extensions, a (short) file defining main() 
which attaches the extensions calls Prolog and the SWI-Prolog kernel 
distributed as a C-library are linked together to form a new executable. 
Using dynamic linking, the extensions are linked to a shared 
library (.so file on most Unix systems) or dynamic-link 
library (.DLL file on Microsoft platforms) and loaded into 
the running Prolog process.73The 
system also contains code to load .o files directly for 
some operating systems, notably Unix systems using the BSD a.out 
executable format. As the number of Unix platforms supporting this gets 
quickly smaller and this interface is difficult to port and slow, it is 
no longer described in this manual. The best alternatively would be to 
use the dld package on machines do not have 
shared libraries.
The static linking schema can be used on all versions of SWI-Prolog. Whether or not dynamic linking is supported can be deduced from the Prolog flag open_shared_object (see current_prolog_flag/2). If this Prolog flag yields true, open_shared_object/2 and related predicates are defined. See section 9.2.3 for a suitable high-level interface to these predicates.
All described approaches have their advantages and disadvantages. Static linking is portable and allows for debugging on all platforms. It is relatively cumbersome and the libraries you need to pass to the linker may vary from system to system, though the utility program plld described in section 9.5 often hides these problems from the user.
Loading shared objects (DLL files on Windows) provides sharing and protection and is generally the best choice. If a saved-state is created using qsave_program/[1,2], an initialization/1 directive may be used to load the appropriate library at startup.
Note that the definition of the foreign predicates is the same, regardless of the linking type used.
This section discusses the functionality of the (autoload) 
library(shlib), providing an interface to manage shared libraries. We 
describe the procedure for using a foreign resource (DLL in Windows and 
shared object in Unix) called mylib.
First, one must assemble the resource and make it compatible to SWI-Prolog. The details for this vary between platforms. The plld(1) utility can be used to deal with this in a portable manner. The typical commandline is:
plld -o mylib file.{c,o,cc,C} ...
Make sure that one of the files provides a global function
install_mylib() that initialises the module using calls to 
PL_register_foreign(). Here is a simple example file mylib.c, which 
creates a Windows MessageBox:
#include <windows.h>
#include <SWI-Prolog.h>
static foreign_t
pl_say_hello(term_t to)
{ char *a;
  if ( PL_get_atom_chars(to, &a) )
  { MessageBox(NULL, a, "DLL test", MB_OK|MB_TASKMODAL);
    PL_succeed;
  }
  PL_fail;
}
install_t
install_mylib()
{ PL_register_foreign("say_hello", 1, pl_say_hello, 0);
}
Now write a file mylib.pl:
:- module(mylib, [ say_hello/1 ]). :- use_foreign_library(foreign(mylib)).
The file mylib.pl can be loaded as a normal Prolog file 
and provides the predicate defined in C.
install_mylib(). If the platform prefixes extern functions 
with =_=, this prefix is added before calling.
      ...
      load_foreign_library(foreign(mylib)),
      ...
| FileSpec | is a specification for absolute_file_name/3. If searching the file fails, the plain name is passed to the OS to try the default method of the OS for locating foreign objects. The default definition of file_search_path/2 searches <prolog home>/lib/<arch> on Unix and <prolog home>/bin on Windows. | 
now. This is similar to using:
:- initialization(load_foreign_library(foreign(mylib))).
but using the initialization/1 wrapper causes the library to be loaded after loading of the file in which it appears is completed, while use_foreign_library/1 loads the library immediately. I.e. the difference is only relevant if the remainder of the file uses functionality of the C-library.
The interface defined in this section allows the user to load shared 
libraries (.so files on most Unix systems, .dll 
files on Windows). This interface is portable to Windows as well as to 
Unix machines providing dlopen(2) (Solaris, Linux, 
FreeBSD, Irix and many more) or shl_open(2) (HP/UX). It 
is advised to use the predicates from section 
9.2.3 in your application.
open_shared_object(File, [], Handle). See also
load_foreign_library/[1,2].
On errors, an exception shared_object(Action, Message) 
is raised. Message is the return value from dlerror().
now implies the 
symbols are resolved immediately rather than lazy (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 flags are 
silently ignored.Below is an outline of the files structure required for statically 
linking SWI-Prolog with foreign extensions. \ldots/pl 
refers to the SWI-Prolog home directory (see the Prolog flag home).
<arch> refers to the architecture 
identifier that may be obtained using the Prolog flag arch.
| .../pl/runtime/<arch>/libpl.a | SWI-Library | 
| .../pl/include/SWI-Prolog.h | Include file | 
| .../pl/include/SWI-Stream.h | Stream I/O include file | 
| .../pl/include/SWI-Exports | Export declarations (AIX only) | 
| .../pl/include/stub.c | Extension stub | 
The definition of the foreign predicates is the same as for dynamic 
linking. Unlike with dynamic linking however, there is no initialisation 
function. Instead, the file \ldots/pl/include/stub.c may be 
copied to your project and modified to define the foreign extensions. 
Below is stub.c, modified to link the lowercase example described later 
in this chapter:
#include <stdio.h>
#include <SWI-Prolog.h>
extern foreign_t pl_lowercase(term, term);
PL_extension predicates[] =
{
/*{ "name",      arity,  function,      PL_FA_<flags> },*/
  { "lowercase", 2       pl_lowercase,  0 },
  { NULL,        0,      NULL,          0 }     /* terminating line */
};
int
main(int argc, char **argv)
{ PL_register_extensions(predicates);
  if ( !PL_initialise(argc, argv) )
    PL_halt(1);
  PL_install_readline();                /* delete if not required */
  PL_halt(PL_toplevel() ? 0 : 1);
}
Now, a new executable may be created by compiling this file and 
linking it to libpl.a from the runtime directory and the 
libraries required by both the extensions and the SWI-Prolog kernel. 
This may be done by hand, or using the plld utility described in 
secrefplld. If the linking is performed `by hand', the command-line 
option -dump-runtime-variables (see section 
2.4) can be used to obtain the required paths, libraries and linking 
options to link the new executable.