我最终试图让SWI-Prolog在C ++上发挥得淋漓尽致。现在,在我开始准确解释我的问题之前,我想先说明我的项目是什么以及我选择了哪些工具来开发解决方案。
我的教授指派我开发一个GUI程序,作为SWI-prolog的前端,这个前端将用C ++开发。我选择使用Qt来设计GUI并使用C ++作为后端来将SWI-Prolog连接到应用程序。此应用程序的用户应该能够输入一些列表,然后选择要通过prolog应用于它们的操作,例如,如果我输入数字列表,然后通过单击按钮,用户获得另一个列表此列表中成对的数字(如果有)。我正在开发一个unix操作系统,更具体地说,是基于archlinux和manjaro的netrunner滚动版本。
我做了一些研究,似乎最好的行动方式是为了使SWI-Prolog(我可能还提到我的教授也推荐这个),是使用Volker Wysk开发的头文件和源文件;作为参考,这里是包含这些文件http://www.volker-wysk.de/swiprolog-c++/index.html
的压缩文件的链接现在这是我的问题:如果你访问了我刚刚给你的页面,你会看到SWI-Prolog界面的这个C ++实现已经很老了:上次它的工作是在2002年。我不得不修改头文件,以便我可以摆脱一些错误,如使用命名空间std或将#include ostream.h更改为#include ostream,所以我设法将错误计数只有两个,我不能设法修复,我认为我将无法做到,因为有两个函数的实现我无法在任何地方找到:函数被声明但是它们被调用时应该运行的代码无法找到
我现在将列出我认为最相关的文件的内容。我安装了最新版本的SWI-Prolog,因此SWI-Prolog.h标头是安装最新prolog(版本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();
}
main.cpp文件的内容
我会复制Volker Wysk制作的标题和源文件的全部内容,但是它太长了,不能适应这里。如果您从链接下载到我已发布的网站,您可以查看它们。接下来是我得到的错误以及他们在.cpp文件中发生的两个相应的代码片段:
// 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:错误:未定义引用`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:错误:未定义引用`pl_copy_term'。
除了我必须对我已经提到的头文件所做的更改之外,我还必须在头文件中修复这行代码:
#include <SWI-Prolog.h>
到此:
#include "/usr/lib/swipl-6.6.5/include/SWI-Prolog.h"
这是因为,否则,编译器会抱怨它无法找到该头文件。
我的猜测是这些函数曾经存在于较旧的SWI-Prolog版本中。关于如何处理这个任务,我没有真正的线索,我试着阅读其他使用volker实现的替代方法,但就像网上有关如何将Prolog与C ++接口的信息一样,几乎没有任何好的信息。
非常感谢你花时间阅读我的问题。如果您的解决方案有效,请告诉我。它不一定是SWI-Prolog,它可以是任何其他Prolog环境,它与C ++很好地接口,并且使用或多或少与SWI-Prolog使用的语法相同,尽管我认为语法已经是所有人的标准的环境中。
答案 0 :(得分:1)
查看Makefile
的{{1}},看起来需要使用一个名为swiprolog-c++-0.1.0
的特殊链接器。因此,您需要使用常用的编译器仅生成目标文件,然后使用该链接器创建可执行文件。
makefile中的plld
行如下所示:
plld
“食谱”行扩展到:
main : main.o prolog.o test.pl
plld -o $@ -ld $(CC) $^ -lstdc++
答案 1 :(得分:0)
包swipl-win是一个可在Linux,MacOS,Windows上运行的SWI-Prolog / Qt界面。我还有很多其他人here,但这些仅限于在Linux上运行......
我想知道为什么,除了Qt特定问题之外,当你有一个“官方”的here时,你选择了一个旧的,没有维护的C ++接口。此接口运行良好,基于异常处理和自动类型转换提供参数验证。然后很容易添加到界面 - 例如,从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 {A#(也称为外语界面)记录here。