Встраивание движка пролога в dll

В последнее время я работал над приложением C ++, которое включает механизм рассуждений пролога, и, как указано в заголовке, теперь я пытаюсь сгенерировать DLL вместо исполняемого файла, чтобы я мог использовать его в другом проекте. Поскольку я новичок в разработке DLL, я подумал, что могу начать с небольшого примера. У меня 3 файла:

  • likes.pl: пример файла пролога, определяющего предикат лайков / 2
  • likes.cpp: определение функции get_food(), которая вызывает PlQuery и возвращает результаты в std::string
  • food.cpp: использование DLL для вывода списка всех видов еды, которые нравятся Сэму

Итак, моя первая попытка была следующей:

swipl-ld -shared -dll -o likes -goal true likes.cpp likes.pl -DLIKES_EXPORTS -v
g++ -o food.exe -s food.cpp -L. -llikes -I. -L"c:/program files (x86)/swipl/lib" -lswipl -I"c:/program files (x86)/swipl/include"

Прежде всего, позвольте мне указать, что когда get_food() возвращает только строку без какого-либо вызова пролога, это работает нормально. Однако после двух дней расследования я не могу понять, как заставить DLL вызывать пролог. Я думаю, что есть две вещи, которые я делаю неправильно, может быть, обе: инициализацию PlEngine и сохраненное состояние.

Я пробовал вызывать PlEngine как в get_food(), так и в food.cpp main(), результат тот же. Так что пока я придерживаюсь первого варианта, поскольку меня больше интересует, чтобы все выполнялось в DLL. Я вижу здесь (встраивание SWI-Prolog в dll), что позже он может быть сделано в DllMain, но также это не рекомендуется. Как лучше всего это сделать? Должен ли я давать food.exe asargv[0] или что-то еще (libswipl.dll? Сохраненное состояние?)

Во-вторых, я заметил, что одно различие при использовании swipl-ld для создания DLL вместо EXE заключается в том, что он пропускает строки:

swipl.exe -f none -F none -g true -t"consult(['likes.pl']),qsave_program('pltmp-4228.exe',[goal=true,toplevel=prolog,init_file=none])"
cat pltmp-4228.exe >> food.exe

Поэтому я попытался сделать это вручную, заменив случайное имя на «mystate.exe» и используя команду Win32 copy /b, чтобы добавить его в food.exe. Это делает food.exe консолью верхнего уровня, на которой я могу тестировать likes/2. Это потому, что в Dll нет main()? В любом случае, это максимум, на что я мог пока прийти, и я думаю, что нужно было изменить несколько вещей во втором аргументе qsave_program/2. Я пробовал заменить toplevel=prolog на stand_alone=true. Кстати, пример команды, приведенный в конце (http://www.swi-prolog.org/pldoc/doc_for?object=section%282,%272.10%27,swi%28%27/doc/Manual/compilation.html%27%29%29) вообще не создает никаких файлов. Во всяком случае, я тоже не могу понять, нужно ли мне это делать и как именно.

Кто-нибудь может сказать мне, как это решить?


person MnaerwwreanM    schedule 05.09.2013    source источник


Ответы (2)


Простите меня, так как это не совсем точный ответ на вашу проблему, просто отчет о моем опыте по этой теме.

Я работал над pqConsole, DLL, которая вводит привязки Qt через интерфейс C ++.

pqConsole, еще находясь в разработке, до сих пор нашла свое применение в swipl-win, и мне посчастливилось работать вместе с Яном Вилемакером, сделав этот маленький большой шаг для расширения аудитории Prolog.

Я бы посоветовал создать вашу DLL с G ++, чтобы получить двоичную совместимость, и выпустить компоненты SWI-Prolog как есть.

Если вам нравится Qt, вы можете использовать QtCreator для дизайна интерфейса, см., Например, fdqueens. Там вы также можете увидеть, как я раньше встраивал .pl в ресурсы проекта Qt, чтобы иметь больший контроль над приложением (пользователи не могут связываться с логикой Prolog, которая требуется из других частей) и над выпуском (нет .pl для добавления, только исполняемый файл / DLL).

HTH

person CapelliC    schedule 05.09.2013
comment
›Я бы посоветовал создать вашу DLL с G ++, чтобы получить двоичную совместимость, и выпустить компоненты SWI-Prolog как есть. Извините, но я не понимаю, что вы здесь имеете в виду. Будет ли в моей DLL только код C ++? Тогда как моя программа сможет использовать все предикаты, определенные в моем коде пролога? Мне нужен способ получить API, вызывающий некоторую логику. Я уверен, что есть способ сделать это правильно и легко (если вы знаете, какие аргументы использовать) в swi-prolog ... - person MnaerwwreanM; 06.09.2013

Решил! На случай, если кому-нибудь когда-нибудь понадобится ответ:

int main(int argc, char *argv[])  {
    char* av[50];
    av[0] = (char*)"food.exe";
    av[1] = (char*)"-x";
    av[2] = (char*)"mystate.exe";
    if(!PL_initialise(3, av))
        cout << "NO init\n" ;
    else
        cout << "OK init\n" ;
    cout <<  get_food() ;
    getchar();
    return 0;
}

Потом:

swipl --goal=true --stand_alone=true -o mystate -c likes.pl
swipl-ld -shared -dll -o likes -goal true likes.cpp likes.pl -DLIKES_EXPORTS -v
g++ -o food.exe food.cpp -L"c:/program files (x86)/swipl/lib" -lswipl -I"c:/program files (x86)/swipl/include" -L. -llikes -I.
person MnaerwwreanM    schedule 09.09.2013