1
votes

I am trying to process a list of numbers i get from a GUI interface made in Qt. In specific, I want to return to the user, in a label, a list of all the numbers that are even in his input list. Thanks to a user CapelliC i managed to include all the files and libraries in order to make SWI-Prolog work from inside C++ and i am now trying to develop the program.

It is required that i use a C++ interface to Prolog in such a way that i receive the list from the user through a QLineEdit object, send the list to the Prolog engine, and then Prolog should return to the C++ program the resulting list of pairs.

I have already made the rule that extracts the pairs from a list and returns it as another list. These are the contents of my manejoListas.pl file, the SWI-Prolog knowledgebase for my program:

pares(Lista,ListaPares):-findall(Numero,(member(Numero,Lista),mod(Numero,2)=:=0),ListaPares).

This works correctly in SWI-Prolog. Now, i want to load this .pl file on my C++ and Qt based program, send the input list to this rule and obtain the resulting list, pointed by the argument ListaPares to my C++ interface so that i can show it to the user.

I have read the Foreign Language Interface documentation and i haven't been able to locate what i need in order to solve this particular scenario. This is what i have so far based blindly on an incomplete "tutorial" i found of somebody on youtube who didn't bother to explain what he was doing for another unrelated problem, mainly, finding the factorial of a number using Qt, C++ and Prolog.

void MainWindow::on_btnPares_clicked()
{
    QString listaEntrada = ui->txtListaEntrada->text();    

    term_t listaEntrada, listaPares, term;
    functor_t paresFunc;

    listaEntrada = PL_new_term_ref();


    listaPares = PL_new_term_ref();

    term = PL_new_term_ref();

    PlCall("consult('manejoListas.pl')"); //I assume this opens my knowledgebase file so that i can work with it

    paresFunc = PL_new_functor(PL_new_atom("pares"), 2);

    PL_cons_functor(term, paresFunc, listaEntrada, listaPares);

    if(PL_call(term, NULL)) {
        PL_get_string()
    }


}

I am unable to advance, i don't know how to pass the list to SWI-Prolog or how to even construct the correct consult i should send to Prolog or how to receive the answer. This program should behave exactly as if i ran the following consult to SWI-Prolog:

?- pares([2,4,8,9],X).
X = [2, 4, 8].

Thank you in advance for any help you can provide.

1

1 Answers

0
votes

It's better to avoid mixing C interface - i.e. term_t, functor_t, PL_new_term_ref() etc - and C++ - i.e. PlCall() etc.

Your code now it's clearly not compilable - maybe you're a bit discouraged by the complexity, but take a breath and keep studying the documentation...

See class PlTail documentation page, there is a simple example of the code required to build a list. OTOH, if you can assume that the list is syntactically correct, some higher level builtin could make your task simpler. For instance, this snippet requires an input list as comma separated numbers:

try {
    QString numbers = QInputDialog::getText(0, "Input numbers separed by comma", "Numbers");
    PlTerm SQLIST = PlAtom(qPrintable("[" + numbers + "]")), NUMLIST, _, SUM;
    if (PlCall("atom_to_term", PlTermv(SQLIST, NUMLIST, _))) {
        if (PlCall("sum_list", PlTermv(NUMLIST, SUM))) {
            QMessageBox::information(0, "sum",
                QString("as string: %1\nas number: %2").arg((const char*)SUM).arg((long)SUM));
        }
    }
}
catch(PlException ex) {
    QMessageBox::critical(0, "exception", (const char*)ex);
}

and then shows how to get back the values - the C++ interface uses a particular style for type conversion and value extraction. With such style, we can obtain very compact code, even in presence of the large 'impendence mismatch' existing between Prolog and C++ (but here I've shown the extended code, without any of the shortcuts I use usually).

Note the try/catch block: it will avoid you many problems, catching syntax and semantic errors - exactly as you get in Prolog interactive shell.

A last tip: always test the return of PlCall - sometime, your code can fail without exceptions...