\documentclass[11pt,a4paper]{report} \usepackage{times} \usepackage{pl} \usepackage{plpage} %\usepackage{xpce} \usepackage{html} \sloppy \onefile \htmloutput{\Sdot} % Output directory \htmlmainfile{pl2cpp} % Main document file \bodycolor{white} % Page colour \renewcommand{\runningtitle}{A C++ interface to SWI-Prolog} \makeindex \begin{document} \title{A C++ interface to SWI-Prolog} \author{Jan Wielemaker \& Peter Ludemann \\ SWI-Prolog Solutions b.v. \\ E-mail: \email{jan@swi-prolog.org}} \maketitle \begin{abstract} This document describes a C++ interface to SWI-Prolog. SWI-Prolog could be used with C++ for a very long time, but only by calling the extern "C" functions of the C-interface. The interface described here provides a true C++ layer around the C-interface for much more concise and natural programming from C++. The interface deals with automatic type-conversion to and from native C data-types, transparent mapping of exceptions, making queries to Prolog and registering foreign predicates. At this moment there are \textbf{two} versions of the C++ interface. \begin{itemize} \item Version 1 is implemented by \file{SWI-cpp.h} and described in \chapref{cpp}. This version is old, suffers from several ambiguities, covers only the core part of the C interface and does not support character encoding issues, which implies \ctype{char*} can only be used to exchange text in ISO-Latin-1 encoding. We hope to deprecate this interface soon. \item Version 2 is implemented by \file{SWI-cpp2.h} and \file{SWI-cpp2.cpp} and described in \chapref{cpp2}. This is a much more mature C++ interface has been designed and implemented by Peter Ludemann. We plan to make this the preferred interface soon. There are still several issues that need to be fully resolved and implemented before this can happen, mostly related to handling text encoding. \end{itemize} \end{abstract} \vfill \vfill \vfill \newpage \tableofcontents \newpage \chapter{A C++ interface to SWI-Prolog (Version 1)} \label{sec:cpp} \section{Introduction} \label{sec:cpp-intro} C++ provides a number of features that make it possible to define a much more natural and concise interface to dynamically typed languages than plain C does. Using programmable type-conversion (\jargon{casting}), native data-types can be translated automatically into appropriate Prolog types, automatic destructors can be used to deal with most of the cleanup required and C++ exception handling can be used to map Prolog exceptions and interface conversion errors to C++ exceptions, which are automatically mapped to Prolog exceptions as control is turned back to Prolog. \subsection*{Competing interfaces} Volker Wysk has defined an alternative C++ mapping based on templates and compatible to the STL framework. See \url{http://www.volker-wysk.de/swiprolog-c++/index.html}. \subsection*{Acknowledgements} I would like to thank Anjo Anjewierden for comments on the definition, implementation and documentation of this package. \section{Overview} \label{sec:cpp-overview} The most useful area for exploiting C++ features is type-conversion. Prolog variables are dynamically typed and all information is passed around using the C-interface type \type{term_t}. In C++, \type{term_t} is embedded in the \jargon{lightweight} class \class{PlTerm}. Constructors and operator definitions provide flexible operations and integration with important C-types (\type{char *}, \type{wchar_t*}, \type{long} and \type{double}). The list below summarises the classes defined in the C++ interface. \begin{description} \classitem{PlTerm} Generic Prolog term. Provides constructors and operators for conversion to native C-data and type-checking. \classitem{PlString} Subclass of \class{PlTerm} with constructors for building Prolog string objects. \classitem{PlCodeList} Subclass of \class{PlTerm} with constructors for building Prolog lists of ASCII values. \classitem{PlCharList} Subclass of \class{PlTerm} with constructors for building Prolog lists of one-character atoms (as \index{atom_chars/2}\predref{atom_chars}{2}). \classitem{PlCompound} Subclass of \class{PlTerm} with constructors for building compound terms. \classitem{PlTail} SubClass of \class{PlTerm} for building and analysing Prolog lists. \classitem{PlTermv} Vector of Prolog terms. See \cfuncref{PL_new_term_refs}{}. the \const{\Snil} operator is overloaded to access elements in this vector. \class{PlTermv} is used to build complex terms and provide argument-lists to Prolog goals. \classitem{PlException} Subclass of \class{PlTerm} representing a Prolog exception. Provides methods for the Prolog communication and mapping to human-readable text representation. \classitem{PlTypeError} Subclass of \class{PlException} for representing a Prolog \except{type_error} exception. \classitem{PlDomainError} Subclass of \class{PlException} for representing a Prolog \except{domain_error} exception. \classitem{PlExistenceError} Subclass of \class{PlException} for representing a Prolog \except{existence_error} exception. \classitem{PlPermissionError} Subclass of \class{PlException} for representing a Prolog \except{permission_error} exception. \classitem{PlAtom} Allow for manipulating atoms in their internal Prolog representation for fast comparison. \classitem{PlQuery} Represents opening and enumerating the solutions to a Prolog query. \classitem{PlFrame} This utility-class can be used to discard unused term-references as well as to do `\jargon{data-backtracking}'. \classitem{PlEngine} This class is used in \jargon{embedded} applications (applications where the main control is held in C++). It provides creation and destruction of the Prolog environment. \classitem{PlRegister} The encapsulation of \cfuncref{PL_register_foreign}{} is defined to be able to use C++ global constructors for registering foreign predicates. \end{description} The required C(++) function header and registration of a predicate is arranged through a macro called \cfuncref{PREDICATE}{}. \section{Examples} \label{sec:cpp-examples} Before going into a detailed description of the C++ classes we present a few examples illustrating the `feel' of the interface. \subsection{Hello(World)} \label{sec:cpp-hello-world} This simple example shows the basic definition of the predicate \index{hello/1}\predref{hello}{1} and how a Prolog argument is converted to C-data: \begin{code} PREDICATE(hello, 1) { cout << "Hello " << (char *)A1 << endl; return TRUE; } \end{code} \noindent The arguments to PREDICATE() are the name and arity of the predicate. The macros A\bnfmeta{n} provide access to the predicate arguments by position and are of the type \class{PlTerm}. Casting a \class{PlTerm} to a \type{char *} or \type{wchar_t *} provides the natural type-conversion for most Prolog data-types, using the output of \index{write/1}\predref{write}{1} otherwise: \begin{code} ?- hello(world). Hello world Yes ?- hello(X) Hello _G170 X = _G170 \end{code} \noindent \subsection{Adding numbers} \label{sec:cpp-ex-adding-numbers} This example shows arithmetic using the C++ interface, including unification, type-checking and conversion. The predicate \index{add/3}\predref{add}{3} adds the two first arguments and unifies the last with the result. \begin{code} PREDICATE(add, 3) { return A3 = (long)A1 + (long)A2; } \end{code} \noindent Casting a \class{PlTerm} to a \type{long} performs a \cfuncref{PL_get_long}{} and throws a C++ exception if the Prolog argument is not a Prolog integer or float that can be converted without loss to a \type{long}. The \const{\Seq} operator of \class{PlTerm} is defined to perform unification and returns \const{TRUE} or \const{FALSE} depending on the result. \begin{code} ?- add(1, 2, X). X = 3. ?- add(a, 2, X). [ERROR: Type error: `integer' expected, found `a'] Exception: ( 7) add(a, 2, _G197) ? \end{code} \noindent \subsection{Average of solutions} \label{sec:cpp-ex-average} This example is a bit harder. The predicate \index{average/3}\predref{average}{3} is defined to take the template \mbox{average(+Var, :Goal, -Average)}, where \arg{Goal} binds \arg{Var} and will unify \arg{Average} with average of the (integer) results. \class{PlQuery} takes the name of a predicate and the goal-argument vector as arguments. From this information it deduces the arity and locates the predicate. the member-function next_solution() yields \const{TRUE} if there was a solution and \const{FALSE} otherwise. If the goal yielded a Prolog exception it is mapped into a C++ exception. \begin{code} PREDICATE(average, 3) { long sum = 0; long n = 0; PlQuery q("call", PlTermv(A2)); while( q.next_solution() ) { sum += (long)A1; n++; } return A3 = (double)sum/(double)n; } \end{code} \noindent \section{The class PlTerm} \label{sec:cpp-plterm} As we have seen from the examples, the \class{PlTerm} class plays a central role in conversion and operating on Prolog data. This section provides complete documentation of this class. \subsection{Constructors} \label{sec:cpp-plterm-constructurs} \begin{description} \constructor{PlTerm}{} Creates a new initialised term (holding a Prolog variable). \constructor{PlTerm}{term_t t} Converts between the C-interface and the C++ interface by turning the term-reference into an instance of \class{PlTerm}. Note that, being a lightweight class, this is a no-op at the machine-level! \constructor{PlTerm}{const char *text} Creates a term-references holding a Prolog atom representing \arg{text}. \constructor{PlTerm}{const wchar_t *text} Creates a term-references holding a Prolog atom representing \arg{text}. \constructor{PlTerm}{const PlAtom \&atom} Creates a term-references holding a Prolog atom from an atom-handle. \constructor{PlTerm}{long n} Creates a term-references holding a Prolog integer representing \arg{n}. \constructor{PlTerm}{double f} Creates a term-references holding a Prolog float representing \arg{f}. \constructor{PlTerm}{void *ptr} Creates a term-references holding a Prolog pointer. A pointer is represented in Prolog as a mangled integer. The mangling is designed to make most pointers fit into a \jargon{tagged-integer}. Any valid pointer can be represented. This mechanism can be used to represent pointers to C++ objects in Prolog. Please note that `myclass' should define conversion to and from \type{void *}. \begin{code} PREDICATE(make_my_object, 1) { myclass *myobj = new myclass(); return A1 = (void *)myobj; } PREDICATE(free_my_object, 1) { myclass *myobj = (void *)A1; delete(myobj); return TRUE; } \end{code} \noindent \end{description} \subsection{Casting PlTerm to native C-types} \label{sec:cpp-plterm-casting} \ctype{PlTerm} can be cast to the following types: \begin{description} \cppcast{PlTerm}{term_t} This cast is used for integration with the C-interface primitives. \cppcast{PlTerm}{long} Yields a \type{long} if the \class{PlTerm} is a Prolog integer or float that can be converted without loss to a long. throws a \except{type_error} exception otherwise. \cppcast{PlTerm}{int} Same as for \type{long}, but might represent fewer bits. \cppcast{PlTerm}{double} Yields the value as a C double if \class{PlTerm} represents a Prolog integer or float. \cppcast{PlTerm}{wchar_t *} \nodescription \cppcast{PlTerm}{char *} Converts the Prolog argument using \cfuncref{PL_get_chars}{} using the flags \const{CVT_ALL|CVT_WRITE|BUF_RING}, which implies Prolog atoms and strings are converted to the represented text. All other data is handed to \index{write/1}\predref{write}{1}. If the text is static in Prolog, a direct pointer to the string is returned. Otherwise the text is saved in a ring of 16 buffers and must be copied to avoid overwriting. \cppcast{PlTerm}{void *} Extracts pointer value from a term. The term should have been created by PlTerm::PlTerm(void*). \end{description} \subsection{Unification} \label{sec:cpp-plterm-unification} \begin{description} \cfunction{int}{PlTerm::operator =}{Type} The operator \const{\Seq} is defined for the \arg{Types} \class{PlTerm}, \type{long}, \type{double}, \type{char *}, \type{wchar_t*} and \class{PlAtom}. It performs Prolog unification and returns \const{TRUE} if successful and \const{FALSE} otherwise. The boolean return-value leads to somewhat unconventional-looking code as normally, assignment returns the value assigned in C. Unification however is fundamentally different to assignment as it can succeed or fail. Here is a common example. \begin{code} PREDICATE(hostname, 1) { char buf[32]; if ( gethostname(buf, sizeof(buf)) == 0 ) return A1 = buf; return FALSE; } \end{code} \noindent \end{description} \subsection{Comparison} \label{sec:cpp-plterm-comparison} \begin{description} \cfunction{int}{PlTerm::operator ==}{const PlTerm \&t} \nodescription \cfunction{int}{PlTerm::operator !=}{const PlTerm \&t} \nodescription \cfunction{int}{PlTerm::operator $<$}{const PlTerm \&t} \nodescription \cfunction{int}{PlTerm::operator $>$}{const PlTerm \&t} \nodescription \cfunction{int}{PlTerm::operator $<=$}{const PlTerm \&t} \nodescription \cfunction{int}{PlTerm::operator $>=$}{const PlTerm \&t} Compare the instance with \arg{t} and return the result according to the Prolog defined \jargon{standard order of terms}. \cfunction{int}{PlTerm::operator ==}{long num} \nodescription \cfunction{int}{PlTerm::operator !=}{long num} \nodescription \cfunction{int}{PlTerm::operator $<$}{long num} \nodescription \cfunction{int}{PlTerm::operator $>$}{long num} \nodescription \cfunction{int}{PlTerm::operator $<=$}{long num} \nodescription \cfunction{int}{PlTerm::operator $>=$}{long num} Convert \class{PlTerm} to a \type{long} and perform standard C-comparison between the two long integers. If \class{PlTerm} cannot be converted a \except{type_error} is raised. \cfunction{int}{PlTerm::operator ==}{const wchar_t *} \nodescription \cfunction{int}{PlTerm::operator ==}{const char *} Yields \const{TRUE} if the \class{PlTerm} is an atom or string representing the same text as the argument, \const{FALSE} if the conversion was successful, but the strings are not equal and an \except{type_error} exception if the conversion failed. \end{description} Below are some typical examples. See \secref{cpp-dirplatom} for direct manipulation of atoms in their internal representation. \begin{center} \begin{tabularlp}{\tt A1 == PlCompound("a(1)")} \hline \tt A1 $<$ 0 & Test \arg{A1} to hold a Prolog integer or float that can be transformed lossless to an integer less than zero. \\ \tt A1 $<$ PlTerm(0) & \arg{A1} is before the term `0' in the `standard order of terms'. This means that if \arg{A1} represents an atom, this test yields \const{TRUE}. \\ \tt A1 == PlCompound("a(1)") & Test \arg{A1} to represent the term \exam{a(1)}. \\ \tt A1 == "now" & Test \arg{A1} to be an atom or string holding the text ``now''. \\ \hline \end{tabularlp} \end{center} \subsection{Analysing compound terms} \label{sec:cpp-plterm-compound} Compound terms can be viewed as an array of terms with a name and arity (length). This view is expressed by overloading the \const{\Snil} operator. A \except{type_error} is raised if the argument is not compound and a \except{domain_error} if the index is out of range. In addition, the following functions are defined: \begin{description} \cfunction{PlTerm}{PlTerm::operator []}{int arg} If the \class{PlTerm} is a compound term and \arg{arg} is between 1 and the arity of the term, return a new \class{PlTerm} representing the arg-th argument of the term. If \class{PlTerm} is not compound, a \except{type_error} is raised. Id \arg{arg} is out of range, a \except{domain_error} is raised. Please note the counting from 1 which is consistent to Prolog's \index{arg/3}\predref{arg}{3} predicate, but inconsistent to C's normal view on an array. See also class \class{PlCompound}. The following example tests \arg{x} to represent a term with first-argument an atom or string equal to \exam{gnat}. \begin{code} ..., if ( x[1] == "gnat" ) ... \end{code} \noindent \cfunction{const char *}{PlTerm::name}{} Return a \type{const char *} holding the name of the functor of the compound term. Raises a \except{type_error} if the argument is not compound. \cfunction{int}{PlTerm::arity}{} Returns the arity of the compound term. Raises a \except{type_error} if the argument is not compound. \end{description} \subsection{Miscellaneous} \label{sec:cpp-plterm-misc} \begin{description} \cfunction{int}{PlTerm::type}{} Yields the actual type of the term as \cfuncref{PL_term_type}{}. Return values are \const{PL_VARIABLE}, \const{PL_FLOAT}, \const{PL_INTEGER}, \const{PL_ATOM}, \const{PL_STRING} or \const{PL_TERM} \end{description} To avoid very confusing combinations of constructors and therefore possible undesirable effects a number of subclasses of \class{PlTerm} have been defined that provide constructors for creating special Prolog terms. These subclasses are defined below. \subsection{The class PlString} \label{sec:cpp-plstring} A SWI-Prolog string represents a byte-string on the global stack. It's lifetime is the same as for compound terms and other data living on the global stack. Strings are not only a compound representation of text that is garbage-collected, but as they can contain 0-bytes, they can be used to contain arbitrary C-data structures. \begin{description} \constructor{PlString}{const wchar_t *text} \nodescription \constructor{PlString}{const char *text} Create a SWI-Prolog string object from a 0-terminated C-string. The \arg{text} is copied. \constructor{PlString}{const wchar_t *text, size_t len} \nodescription \constructor{PlString}{const char *text, size_t len} Create a SWI-Prolog string object from a C-string with specified length. The \arg{text} may contain 0-characters and is copied. \end{description} \subsection{The class PlCodeList} \label{sec:cpp-codelist} \begin{description} \constructor{PlCodeList}{const wchar_t *text} \nodescription \constructor{PlCodeList}{const char *text} Create a Prolog list of ASCII codes from a 0-terminated C-string. \end{description} \subsection{The class PlCharList} \label{sec:cpp-plcharlist} Character lists are compliant to Prolog's \index{atom_chars/2}\predref{atom_chars}{2} predicate. \begin{description} \constructor{PlCharList}{const wchar_t *text} \nodescription \constructor{PlCharList}{const char *text} Create a Prolog list of one-character atoms from a 0-terminated C-string. \end{description} \subsection{The class PlCompound} \label{sec:cpp-plcompound} \begin{description} \constructor{PlCompound}{const wchar_t *text} \nodescription \constructor{PlCompound}{const char *text} Create a term by parsing (as \index{read/1}\predref{read}{1}) the \arg{text}. If the \arg{text} is not valid Prolog syntax, a \except{syntax_error} exception is raised. Otherwise a new term-reference holding the parsed text is created. \constructor{PlCompound}{const wchar_t *functor, PlTermv args} \nodescription \constructor{PlCompound}{const char *functor, PlTermv args} Create a compound term with the given name from the given vector of arguments. See \class{PlTermv} for details. The example below creates the Prolog term \exam{hello(world)}. \begin{code} PlCompound("hello", PlTermv("world")) \end{code} \noindent \end{description} \subsection{The class PlTail} \label{sec:pltail} The class \class{PlTail} is both for analysing and constructing lists. It is called \class{PlTail} as enumeration-steps make the term-reference follow the `tail' of the list. \begin{description} \constructor{PlTail}{PlTerm list} A \class{PlTail} is created by making a new term-reference pointing to the same object. As \class{PlTail} is used to enumerate or build a Prolog list, the initial \arg{list} term-reference keeps pointing to the head of the list. \cfunction{int}{PlTail::append}{const PlTerm \&element} Appends \arg{element} to the list and make the \class{PlTail} reference point to the new variable tail. If \arg{A} is a variable, and this function is called on it using the argument \exam{"gnat"}, a list of the form \exam{[gnat|B]} is created and the \class{PlTail} object now points to the new variable \arg{B}. This function returns \const{TRUE} if the unification succeeded and \const{FALSE} otherwise. No exceptions are generated. The example below translates the main() argument vector to Prolog and calls the prolog predicate \index{entry/1}\predref{entry}{1} with it. \begin{code} int main(int argc, char **argv) { PlEngine e(argv[0]); PlTermv av(1); PlTail l(av[0]); for(int i=0; i #include PREDICATE(pi, 1) { A1 = M_PI; } \end{code} \noindent \begin{code} ?- math:pi(X). X = 3.14159 \end{code} \noindent \section{Exceptions} \label{sec:cpp-exceptions} Prolog exceptions are mapped to C++ exceptions using the subclass \class{PlException} of \class{PlTerm} to represent the Prolog exception term. All type-conversion functions of the interface raise Prolog-compliant exceptions, providing decent error-handling support at no extra work for the programmer. For some commonly used exceptions, subclasses of \class{PlException} have been created to exploit both their constructors for easy creation of these exceptions as well as selective trapping in C++. Currently, these are \class{PlTypeEror} and \class{PlDomainError}. To throw an exception, create an instance of \class{PlException} and use throw(). \begin{code} char *data = "users"; throw PlException(PlCompound("no_database", PlTerm(data))); \end{code} \noindent \subsection{The class PlException} \label{sec:cpp-plexception} The C++ model of exceptions and the Prolog model of exceptions are different. Wherever the underlying function returns a "fail" return code, the C++ API does a further check for whether there's an exception and, if so, does a C++ \exam{throw} of a \class{PlException} object. You can use C++ try-catch to intercept this and examine the This subclass of \class{PlTerm} is used to represent exceptions. Currently defined methods are: \begin{description} \constructor{PlException}{} Create an exception term using \cfuncref{PL_exception}{0}. The method is_null() succeeds if there was simple failure (e.g., from unification failing) and not_null() succeeds if there was an exception. \constructor{PlException}{const PlTerm \&t} Create an exception from a general Prolog term. This provides the interface for throwing any Prolog terms as an exception. \cppcast{PlException}{wchar_t *} \nodescription \cppcast{PlException}{char *} The exception is translated into a message as produced by \index{print_message/2}\predref{print_message}{2}. The character data is stored in a ring. Example: \begin{code} ...; try { PlCall("consult(load)"); } catch ( PlException &ex ) { cerr << (char *) ex << endl; } \end{code} \noindent \cfunction{int}{plThrow}{} Used in the PREDICATE() wrapper to pass the exception to Prolog. See \cfuncref{PL_raise_exeption}{}. \cfunction{int}{cppThrow}{} Used by PlQuery::next_solution() to refine a generic \class{PlException} representing a specific class of Prolog exceptions to the corresponding C++ exception class and finally then executes throw(). Thus, if a \class{PlException} represents the term \begin{quote} \term{error}{\term{type_error}{Expected, Actual}, Context} \end{quote} PlException::cppThrow() throws a \class{PlTypeEror} exception. This ensures consistency in the exception-class whether the exception is generated by the C++-interface or returned by Prolog. The following example illustrates this behaviour: \begin{code} PREDICATE(call_atom, 1) { try { return PlCall((char *)A1); } catch ( PlTypeError &ex ) { cerr << "Type Error caugth in C++" << endl; cerr << "Message: \"" << (char *)ex << "\"" << endl; return FALSE; } } \end{code} \noindent \end{description} \subsection{The class PlTypeError} \label{sec:cpp-pl-type-error} A \jargon{type error} expresses that a term does not satisfy the expected basic Prolog type. \begin{description} \constructor{PlTypeError}{const char *expected, const PlTerm \&actual} Creates an ISO standard Prolog error term expressing the \arg{expected} type and \arg{actual} term that does not satisfy this type. \end{description} \subsection{The class PlDomainError} \label{sec:cpp-pl-domain-error} A \jargon{domain error} expresses that a term satisfies the basic Prolog type expected, but is unacceptable to the restricted domain expected by some operation. For example, the standard Prolog \index{open/3}\predref{open}{3} call expect an \const{io_mode} (read, write, append, ...). If an integer is provided, this is a \jargon{type error}, if an atom other than one of the defined io-modes is provided it is a \jargon{domain error}. \begin{description} \constructor{PlDomainError}{const char *expected, const PlTerm \&actual} Creates an ISO standard Prolog error term expressing a the \arg{expected} domain and the \arg{actual} term found. \end{description} \section{Embedded applications} \label{sec:cpp-embedding} Most of the above assumes Prolog is `in charge' of the application and C++ is used to add functionality to Prolog, either for accessing external resources or for performance reasons. In some applications, there is a \jargon{main-program} and we want to use Prolog as a \jargon{logic server}. For these applications, the class \class{PlEngine} has been defined. Only a single instance of this class can exist in a process. When used in a multi-threading application, only one thread at a time may have a running query on this engine. Applications should ensure this using proper locking techniques.% \footnote{For Unix, there is a multi-threaded version of SWI-Prolog. In this version each thread can create and destroy a thread-engine. There is currently no C++ interface defined to access this functionality, though ---of course--- you can use the C-functions.} \begin{description} \constructor{PlEngine}{int argc, char **argv} Initialises the Prolog engine. The application should make sure to pass \exam{argv[0]} from its main function, which is needed in the Unix version to find the running executable. See \cfuncref{PL_initialise}{} for details. \constructor{PlEngine}{char *argv0} Simple constructure using the main constructor with the specified argument for \exam{argv[0]}. \destructor{PlEngine} Calls \cfuncref{PL_cleanup}{} to destroy all data created by the Prolog engine. \end{description} \Secref{pltail} has a simple example using this class. \section{Considerations} \label{sec:cpp-considerations} \subsection{The C++ versus the C interface} \label{sec:cpp-vs-c} Not all functionality of the C-interface is provided, but as \class{PlTerm} and \type{term_t} are essentially the same thing with automatic type-conversion between the two, this interface can be freely mixed with the functions defined for plain C. Using this interface rather than the plain C-interface requires a little more resources. More term-references are wasted (but reclaimed on return to Prolog or using \class{PlFrame}). Use of some intermediate types (\type{functor_t} etc.) is not supported in the current interface, causing more hash-table lookups. This could be fixed, at the price of slighly complicating the interface. \subsection{Static linking and embedding} \label{sec:cpp-linking} The mechanisms outlined in this document can be used for static linking with the SWI-Prolog kernel using \manref{swipl-ld}{1}. In general the C++ linker should be used to deal with the C++ runtime libraries and global constructors. \subsection{Status and compiler versions} \label{sec:cpp-status} The current interface is entirely defined in the \fileext{h} file using inlined code. This approach has a few advantages: as no C++ code is in the Prolog kernel, different C++ compilers with different name-mangling schemas can cooperate smoothly. Also, changes to the header file have no consequences to binary compatibility with the SWI-Prolog kernel. This makes it possible to have different versions of the header file with few compatibility consequences. \section{Conclusions} \label{sec:conclusions} \label{sec:cpp-conclusions} In this document, we presented a high-level interface to Prolog exploiting automatic type-conversion and exception-handling defined in C++. Programming using this interface is much more natural and requires only little extra resources in terms of time and memory. Especially the smooth integration between C++ and Prolog exceptions reduce the coding effort for type checking and reporting in foreign predicates. \input{pl2cpp2} \printindex \end{document}