SWI-Prolog 与 C++ 的接口问题 [英] Problems interfacing SWI-Prolog to C++

查看:75
本文介绍了SWI-Prolog 与 C++ 的接口问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我竭尽全力使 SWI-Prolog 与 C++ 兼容.现在,在我开始确切地解释我的问题是什么之前,我想首先说明我的项目是关于什么以及我选择了哪些工具来开发解决方案.

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.

我的教授分配给我的任务是开发一个 GUI 程序,作为 SWI-prolog 的前端,这个前端将用 C++ 开发.我选择使用 Qt 来设计 GUI,并使用 C++ 作为后端将 SWI-Prolog 桥接到应用程序.这个应用程序的用户应该能够输入一些列表,然后通过 prolog 选择要应用于它们的操作,例如,如果我输入一个数字列表,然后通过点击一个按钮,用户会得到另一个所有列表此列表中成对的数字(如果有).我正在 unix 操作系统上进行开发,更具体地说,是基于 archlinux 和 manjaro 的 netrunner 滚动版本.

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.

我做了一些研究,似乎最好的方法是使用由 Volker Wysk 开发的头文件和源文件,以便与 SWI-Prolog 接口(我还可以提到我的教授也推荐了这个);作为参考,这里是包含这些文件的压缩文件的链接 http://www.volker-wysk.de/swiprolog-c++/index.html

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

现在我的问题是:如果你访问我刚刚给你的页面,你会发现这个 SWI-Prolog 接口的 C++ 实现已经很老了:上次使用它是在 2002 年.我不得不修改头文件,以便我可以摆脱一些错误,例如将 using namespace std 或将 #include ostream.h 更改为 #include ostream,因此我设法将错误计数设置为只有两个我不能设法修复,我认为我将无法修复,因为有两个函数的实现我在任何地方都找不到:该函数已声明,但找不到在调用它们时应该运行的代码.

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.

我现在将列出我认为最相关的文件的内容.我安装了最新版本的 SWI-Prolog,因此 SWI-Prolog.h 标头是安装最新的 prolog(6.6.5 版)时附带的最新标头.

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

prologFrontend.pro 文件(Qt 创建者项目文件)的内容

#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();
}

ma​​in.cpp 文件的内容

我会复制由 Volker Wysk 制作的头文件和源文件的全部内容,但是太长了,无法放在这里.如果你从我已经发布的他的网站的链接下载它,你可以看看它们.接下来是我得到的错误和两个相应的代码片段,它们出现在他制作的 .cpp 文件中:

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;
}

以及这段代码抛出的错误:/usr/local/share/swiprolog-c++/prolog.cpp:45: error: undefined reference to `pl_atom_to_term'.

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);
}

以及此代码抛出的错误:/usr/local/share/swiprolog-c++/prolog.cpp:60: error: undefined reference to `pl_copy_term'.

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>

为此:

#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.

我的猜测是这些函数曾经存在于较旧的 SWI-Prolog 版本中.我对如何处理这个任务没有真正的线索,我尝试阅读使用 volker 实现的其他替代方案,但似乎网络上几乎没有关于如何将 Prolog 与 C++ 接口的好信息.

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++.

非常感谢您花时间阅读我的问题.如果您有有效的解决方案,请告诉我.它不一定是 SWI-Prolog,它可以是任何其他 Prolog 环境,它可以很好地与 C++ 接口并且使用或多或少与 SWI-Prolog 使用的语法相同的语法,尽管我认为该语法已经是所有标准环境.

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.

推荐答案

Package swipl-win 是一个有效的 SWI-Prolog/Qt 接口,可在 Linux、MacOS、Windows 上移植.我还有很多其他的这里,但现在这些仅限于在 Linux 上运行......

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...

我想知道为什么除了 Qt 特定问题之外,您还选择了一个旧的、未维护的 C++ 接口,而有一个官方"接口 此处.该接口运行良好,基于异常处理和自动类型转换提供参数验证.然后很容易添加到界面 - 例如,从 PREDICATE.h

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__ };
...

允许

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();
}

关于你的具体问题,可能那些功能已经过时了,你应该坚持使用 C Api(也称为外语接口)文档此处.

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

这篇关于SWI-Prolog 与 C++ 的接口问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆