列表处理在Prolog中使用的c++接口

List processing in Prolog using a C++ interface

本文关键字:c++ 接口 表处理 Prolog 列表      更新时间:2023-10-16

我正试图处理从Qt中制作的GUI界面获得的数字列表,具体而言,我想返回给用户,在标签中,甚至在他的输入列表中所有数字的列表。感谢用户CapelliC,我设法包括所有的文件和库,以使sw - prolog工作从c++内部,我现在正试图开发程序。

要求我使用c++接口来Prolog,这样我就可以通过QLineEdit对象从用户那里接收列表,将列表发送给Prolog引擎,然后Prolog应该返回给c++程序生成的对列表。

我已经制定了从列表中提取对并将其作为另一个列表返回的规则。以下是我的manejoListas.pl文件的内容,它是我的程序的SWI-Prolog知识库:

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

这在SWI-Prolog中正确工作。现在,我想在我的基于c++和Qt的程序中加载这个.pl文件,将输入列表发送到该规则并获得结果列表,由参数ListaPares指向我的c++接口,以便我可以将其显示给用户。

我已经阅读了外语接口文档,我还没能找到我需要什么来解决这个特殊的场景。这是我到目前为止盲目地基于一个不完整的"教程",我发现有人在youtube上没有费心解释他在做另一个不相关的问题,主要是用Qt, c++和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()
    }

}

我无法前进,我不知道如何将列表传递给SWI-Prolog或如何构建我应该发送给Prolog的正确咨询或如何接收答案。这个程序的行为应该完全像我运行以下命令一样,请参阅SWI-Prolog:

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

事先感谢您提供的任何帮助

最好避免将C接口(即term_t, functor_t, PL_new_term_ref()等)与c++接口(即PlCall()等)混合使用。

你的代码现在显然是不可编译的-也许你有点气馁的复杂性,但深呼吸,继续研究文档…

参见类PlTail文档页面,有一个构建列表所需的简单代码示例。当然,如果您可以假设该列表在语法上是正确的,那么一些更高级别的内置功能可以使您的任务更简单。例如,这个代码片段需要一个以逗号分隔的数字的输入列表:

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: %1nas number: %2").arg((const char*)SUM).arg((long)SUM));
        }
    }
}
catch(PlException ex) {
    QMessageBox::critical(0, "exception", (const char*)ex);
}

,然后展示如何返回值——c++接口使用特定的样式进行类型转换和值提取。有了这种风格,我们可以获得非常紧凑的代码,即使Prolog和c++之间存在很大的"阻抗不匹配"(但这里我展示了扩展的代码,没有我通常使用的任何快捷方式)。

注意try/catch块:它将避免许多问题,捕获语法和语义错误-就像你在Prolog交互式shell中得到的一样。

最后一个提示:总是测试PlCall的返回-有时,你的代码可能失败没有异常…