3

i am at wit's end trying to make SWI-Prolog play nice with C++. Now, before i start explaining exactly what my problem is, i want to first state what my project is about and what tools i chose in order to develop a solution.

My professor assigned to me the task of developing a GUI program that serves as a frontend to SWI-prolog, and this frontend is to be developed in C++. I chose to use Qt to design the GUI and use C++ as a backend to bridge SWI-Prolog to the application. The user of this application should be able to input some lists and then choose operations to be applied to them through prolog, like if, for example, I input a list of numbers, then by click of a button the user gets another list of all the numbers that are pairs in this list (if there are any). I am developing on a unix OS, more specifically, netrunner rolling release, based on archlinux and manjaro.

I did some research, and it seemed that the best course of action in order to interface SWI-Prolog (may i also mention that my professor also recommended this), is to use the header and source file developed by Volker Wysk; for reference, here is the link to the compressed file that contains these files http://www.volker-wysk.de/swiprolog-c++/index.html

Now here is my problem: if you visited the page i just gave you you will see that this C++ implementation of the SWI-Prolog interface is quite old: last time it was worked on was in the year 2002. I had to modify the header file so that i could get rid of some of the errors, like putting using namespace std or changing #include ostream.h to #include ostream, and so i managed to get the error count to only two which i can't manage to fix and which i think i won't be able to because there are two functions whose implementation i can't find anywhere: the function is declared but the code that it is supposed to run when they are called can't be found.

I will now list the contents of the files i consider to be most relevant. I have the latest version of SWI-Prolog installed, and so the SWI-Prolog.h header is the latest one that comes with the installation of the newest prolog (version 6.6.5).

#-------------------------------------------------
#
# Project created by QtCreator 2014-07-05T12:38:45
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = prologFrontend
TEMPLATE = app


SOURCES += main.cpp\
        mainwindow.cpp \
    ../../../../../../../../usr/local/share/swiprolog-c++/prolog.cpp

LIBS += -L/usr/lib/swipl-6.6.5/lib/x86_64-linux -lswipl

HEADERS  += mainwindow.h

FORMS    += mainwindow.ui

contents of the prologFrontend.pro file (Qt creator project file)

#include "mainwindow.h"
#include <QApplication>
#include <prolog.hpp>


int main(int argc, char *argv[])
{
    try {
        Prolog_impl::prolog_init(argc, argv);

    } catch(Prolog_impl::PlError &error) {

    }


    QApplication prog(argc, argv);
    MainWindow w;
    w.show();

    return prog.exec();
}

contents of the main.cpp file

I would copy the whole contents of the header and source files made by Volker Wysk, but it's too long to fit in here. You can take a look at them if you download it from the link to his site i already posted. Next are the errors i am getting and the two corresponding code snippets where they happen in the .cpp file that he made:

// part of SWI-Prolog, but not exportet by header file
// /usr/local/src/swiprolog-4.0.9/src/pl-funcs.h

//NOTE: this function is declared here but it's even not to be found in the header file
//prolog.hpp. Its implementation can't be found anywhere using the function definition
//navigation capability of Qt so, basically, its a function that does nothing.
extern "C"{
unsigned long pl_atom_to_term(term_t in_atom,
                              term_t out_term,
                              term_t out_bindings);

}

bool Prolog_impl::atom_to_term(const char* text, Term* t, list<Term::Binding>* b)
{
  Term in_atom = Atom(text);
  Term out_term;
  Term out_bindings;

  if (!pl_atom_to_term(in_atom.lsi, out_term.lsi, out_bindings.lsi))
    return false;

  if (t) *t = out_term;
  if (b) *b = out_bindings;
  return true;
}

And the error that this code throws: /usr/local/share/swiprolog-c++/prolog.cpp:45: error: undefined reference to `pl_atom_to_term'.

//Note that this code has the same issues as the one above: no implementation to be found
extern "C"{
unsigned long pl_copy_term(term_t in, term_t out);
}

Term Prolog_impl::copy_term(Term t)
{
  term_t t2 = PL_new_term_ref();
  if (!pl_copy_term(t.lsi, t2))
    throw LogicError("copy_term(Term)", "failure calling pl_copy_term()");
  return Term(t2);
}

and the error that this code throws: /usr/local/share/swiprolog-c++/prolog.cpp:60: error: undefined reference to `pl_copy_term'.

Aside from the changes I had to make to the header file I already mentioned, I had to fix this line of code in the header file:

#include <SWI-Prolog.h>

to this:

#include "/usr/lib/swipl-6.6.5/include/SWI-Prolog.h"

This is because, otherwise, the compiler complains that it can't find that header file.

My guess is that these functions used to exist in an older SWI-Prolog version. I have no real clue about what to do with this task, i tried reading up on other alternatives to using volker's implementation but it's like there is close to none good information on the net about how to interface Prolog with C++.

Thank you so very much for taking your time to read my question. If you have a solution that works, please let me know. It doesn't have to be SWI-Prolog, it could be any other Prolog environment that interfaces nicely with C++ and that uses more or less about the same syntax that SWI-Prolog uses, though i think that the syntax is already standard for all environments.

Greg
  • 403
  • 2
  • 6
  • 16

2 Answers2

1

Looking into the Makefile for swiprolog-c++-0.1.0, it looks like a special linker needs to be used, called plld. So you need to use your usual compiler to generate only the object files, then use that linker to create the executable.

The plld line in the makefile looks like this:

main : main.o prolog.o test.pl
    plld -o $@ -ld $(CC) $^ -lstdc++

The "recipe" line expands to this:

plld -o main -ld gcc main.o prolog.o test.pl -lstdc++
ooga
  • 15,423
  • 2
  • 20
  • 21
  • 1
    [plld](http://www.swi-prolog.org/pldoc/man?section=plld) has a specialized role in building embedded applications or SWI-Prolog kernel, I don't use it when interfacing Qt - instead, pkg-config is useful, at least when Swi-Prolog has been built from sources – CapelliC Jul 07 '14 at 06:21
1

Package swipl-win is a working SWI-Prolog / Qt interface, portable on Linux,MacOS,Windows. I have many others here, but these are restricted to running on Linux by now...

I wonder why, apart Qt specific problems, have you chosen an old, unmaintained C++ interface, when there is an 'official' one here. This interface is working pretty well, giving parameter validation based on exception handling and automatic type conversion. Then it's easy to add to the interface - for instance, from PREDICATE.h

typedef PlTerm T;
#define LOOP__ { } operator bool() { return next_solution(); }
#define query0(P) struct P : PlQuery { P() : PlQuery(#P, V()) LOOP__ };
#define query1(P) struct P : PlQuery { P(T A) : PlQuery(#P, V(A)) LOOP__ };
...

allows

query1(current_predicate)

void Completion::initialize(QSet<QString> &strings, bool reload) {
    Q_UNUSED(reload)
    T PRED;
    for (current_predicate cp(PRED); cp; ) {
        QString p = t2w(PRED);
        if (p[0].isLetter())
            strings.insert(p);
    }
    qDebug() << "Completion::initialize loaded" << strings.count();
}

About your specific problems, probably those functions are obsolete, you should stick to C Api (also know as foreign language interface) documented here.

CapelliC
  • 59,646
  • 5
  • 47
  • 90
  • There is something i don't understand. If you refer to this link http://www.swi-prolog.org/FAQ/CppBinding.html , it says there are actually two c++ bindings: one that is included in the swi-prolog installation, made by Jan Wielemaker (i assume this is the one you are referring to), and another, made by Volker Wysk. Now, quoting Jan Wielemaker, he says that " In due time, if it turns out that Volkers one is working properly and better it is likely to replace my version". What libraries do i need to include in my project to make this all work, aside from SWI-Prolog.h? Any .so libraries? – Greg Jul 07 '14 at 14:30
  • well, note: **if** it turns out that Volkers one is working properly and better... Jan has evolved the C++ interface, as we worked together while integrating Qt. C++ interface it's an 'header only' component, you don't need any additional library. I will place a wiki comment on the page you linked, signalling the problems you incurred. – CapelliC Jul 07 '14 at 14:48
  • I've placed a comment on [that page](http://www.swi-prolog.org/FAQ/CppBinding.html). I'd like to know if in your opinion it is appropriate. – CapelliC Jul 07 '14 at 14:59
  • I managed to succesfully compile the program, linking the swi-prolog shared library, as well as including, in Qt, the path to the header files that come with the SWI-Prolog installation using INCLUDEPATH, so i am discarding Volker's implementation. Have not written any code yet, but i am sure it works now. Another question: are there any tutorials i could use to learn how to use C++ with prolog as a logic server? meaning, i have a .pl file with the rules and facts and make consults from the GUI? On another note, I think the comment you wrote on that page is appropiate. – Greg Jul 08 '14 at 01:16
  • sorry, I can't recall any tutorial. I've some code [here](https://github.com/CapelliC/fdqueens), but it highlights some 'difficult' point, and maybe it's not appropriate for a beginner. – CapelliC Jul 08 '14 at 05:30
  • I've just started writing a micro tutorial, when I've done I'll add a reference here... – CapelliC Jul 08 '14 at 05:43
  • 1
    I've posted a [micro tutorial](http://prolog-in-the-wild.blogspot.com/2014/07/tutorial-minimal-qt-interface-to-swi.html) on blogger... HTH – CapelliC Jul 08 '14 at 09:34
  • Thank you very much CappeliC. Will give it a go :) – Greg Jul 08 '14 at 18:43