In another thread, the topic of SWI-cpp.h (a C++ wrapper around the C interface for foreign predicates) has come up; and it appears that we need to make some changes.
So, my first question is: who uses SWI-cpp.h? So far, I only know of the pack(rocksdb) and swipl-win.
At a high level, these are my proposed changes (so far):
- Remove the use of the assignment operator for unification, replacing by
unify()
andunify_ex()
methods.- the signature (returning a
bool
instead of aPlTerm&
) is unexpected and error-prone.
- the signature (returning a
- Replace most of the overloaded
PlTerm
constructors “tagged” constructors. (*)- The underlying C interface uses
unsigned long
for atoms and terms, so the compiler can’t distinguish between creating a term from an atom and creating a term from auint64_t
orsize_t
.
- The underlying C interface uses
- Remove most of the user-defined conversion operators and replace them by “getTYPE()” methods
- The implicit conversions have hidden some typos.
- The conversion operators have the same problem that constructors have, namely the compiler isn’t able to distinguish between
term_t
,atom_t
, etc. andunsigned long
oruint64_t
. (**)
- Remove the
==
operator and replace byeq()
with a tag- Again, because the compiler can’t distinguish between
term_t
anduint64_t
.
- Again, because the compiler can’t distinguish between
- Some housekeeping changes, such as changing
int
tobool
and removing dangerous copy constructors and assignment operators. - Add a wrapper for atom “blobs”.
In making these changes, I will update pack(rocksdb) and swipl-win. If there is other code that depends on SWI-cpp.h, please tell me about them and I’ll make the necessary changes there.
Of course, if people disagree with what I’m proposing, please speak up! - either here or by filing and issue: Issues · SWI-Prolog/packages-cpp · GitHub
My general approach to C++ is to avoid fancy features as much as possible, and to follow the recommendations of the Google C++ Style Guide (but allowing exceptions, because they greatly simplify SWI-cpp.h).
(*) This is a simpler version of the “tags” that the Boost library uses. An extra argument is added so that the compiler can overload the constructor, for example:
PlTerm::PlTerm(term_t t, const asTermT_tag&)
PlTerm::PlTerm(uint64_t, const asUint64T_tag&)
and then used by:
PlTerm p1(t, asTermT);
PlTerm p2(1234, asIntT);
(**) An alternative would be to edit SWI-Prolog.h
, replacing term_t
by struct{uintptr_t t}
(and similarly for atom_t
, functor_t
, etc. … this would require extensive editing of the SWI-Prolog source code. It would possibly catch some typos in the code, but it’s unlikely that such typos exist, or are significant. (BTW, in some of my code I accidentally wrote atom_t
instead of term_t
, but that didn’t break anything; it merely made my code a bit inscrutable.