Я работал над приложением C ++, которое в последнее время встраивает механизм рассуждений пролога, и, как указано в заголовке, я сейчас пытаюсь сгенерировать DLL вместо исполняемого файла, чтобы я мог использовать ее в другом проекте. Поскольку я новичок в разработке DLL, я подумал, что могу начать с небольшого примера. У меня есть 3 файла:
likes.pl
: пример файла пролога, определяющего предикаты лайков / 2likes.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-пролога в dll) что позже это можно сделать в DllMain
но и то, что это не рекомендуется. Каков наилучший способ сделать это? Должен ли я дать food.exe какargv[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) не создает никаких файлов вообще. Во всяком случае, я не могу понять, если и как именно я должен это сделать.
Может кто-нибудь сказать мне, как это решить?
Простите, так как это не совсем точный ответ на вашу проблему, просто отчет о моем опыте по этой теме.
Я работал над pqConsole, DLL, которая вводит привязки Qt через интерфейс C ++.
Пока pqConsole еще находится в разработке, она нашла свой путь в swipl выигрыша, и я имел удовольствие работать вместе с Яном Вилемейкером, делая этот маленький большой шаг для расширения аудитории Пролога.
Я бы предложил собрать вашу DLL с G ++, чтобы получить двоичную совместимость, и выпустить компоненты SWI-Prolog как есть.
Если вам нравится Qt, вы можете использовать QtCreator для дизайна интерфейса, см., Например, fdqueens.
Там вы также можете увидеть, как я встраивал .pl в проект Qt. Ресурсы, иметь больше контроля над приложением (пользователи не могут связываться с логикой Пролога, которая требуется из других частей) и над выпуском (без добавления .pl, только исполняемый файл / DLL).
НТН
Решил это! Если кто-то когда-нибудь нуждается в ответе:
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.