Проблемы сопряжения SWI-Пролога с переполнением стека

Я на грани остроумия, пытаясь заставить SWI-Prolog хорошо играть с C ++. Теперь, прежде чем я начну объяснять, в чем конкретно заключается моя проблема, я хочу сначала указать, о чем мой проект и какие инструменты я выбрал для разработки решения.

Мой профессор поручил мне задачу по разработке программы с графическим интерфейсом, которая служит интерфейсом к SWI-прологу, и этот интерфейс должен быть разработан на C ++. Я решил использовать Qt для разработки GUI и использовать C ++ в качестве бэкэнда для подключения SWI-Prolog к приложению. Пользователь этого приложения должен иметь возможность вводить некоторые списки и затем выбирать операции, которые будут применены к ним через пролог, например, если, например, я ввожу список чисел, то одним нажатием кнопки пользователь получает другой список всех числа, которые являются парами в этом списке (если они есть). Я занимаюсь разработкой для ОС Unix, а точнее, для выпуска netrunner, основанной на archlinux и manjaro.

Я провел некоторое исследование, и казалось, что лучший способ действий для интерфейса 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 является последним, который поставляется с установкой новейшего пролога (версия 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 = appSOURCES += 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 creator)

#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, хотя я думаю, что синтаксис уже является стандартным для всех сред.

2

Решение

пакет swipl выигрыша это рабочий интерфейс SWI-Prolog / Qt, переносимый на Linux, MacOS, Windows. У меня много других Вот, но они ограничены для запуска на Linux сейчас …

Интересно, почему, кроме особых проблем Qt, вы выбрали старый, не поддерживаемый интерфейс 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 Api (также известного как интерфейс на иностранном языке) Вот.

0

Другие решения

Глядя в Makefile за swiprolog-c++-0.1.0Похоже, нужно использовать специальный компоновщик, называемый plld, Поэтому вам нужно использовать обычный компилятор для генерации только объектных файлов, а затем использовать этот компоновщик для создания исполняемого файла.

plld строка в make-файле выглядит так:

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

Строка «рецепт» расширяется до этого:

plld -o main -ld gcc main.o prolog.o test.pl -lstdc++
1

По вопросам рекламы [email protected]