Intégration du moteur de prolog dans une DLL

Je travaille depuis peu sur une application C ++ qui intègre un moteur de raisonnement prolog et, comme indiqué dans le titre, j’essaie maintenant de générer une DLL plutôt qu’un exécutable afin de pouvoir l’utiliser dans un autre projet. Étant donné que je suis nouveau dans le développement de DLL, je pensais pouvoir commencer par un petit exemple. J’ai 3 fichiers:

  • likes.pl : exemple de fichier prolog définissant le prédicat likes / 2
  • likes.cpp : définissant la fonction get_food() qui appelle PlQuery et renvoie les résultats dans un std::ssortingng
  • food.cpp : utiliser la DLL pour répertorier tous les types d’aliments que Sam aime

Donc, mon premier essai a été le suivant:

 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" 

Tout d’abord, permettez-moi de souligner que lorsque get_food() renvoie uniquement une chaîne sans aucun appel à prolog, cela fonctionne correctement. Cependant, après deux jours d’enquête, je ne vois pas comment faire en sorte que la DLL appelle prolog. Je pense que je peux faire quelque chose de mal, peut-être les deux: l’initialisation de PlEngine et l’état enregistré.

J’ai essayé d’appeler PlEngine dans get_food() et dans food.cpp main() , même résultat. Donc, pour l’instant, je m’en tiens à la première option car je suis plus intéressé par tout faire dans la DLL. Je vois ici (en intégrant SWI-Prolog dans une dll ) que cela peut être fait plus tard dans DllMain mais que cela n’est pas recommandé. Quelle est la meilleure façon de le faire? Dois-je donner à food.exe argv[0] ou quelque chose d’autre (libswipl.dll? Un état enregistré?)

Deuxièmement, j’ai remarqué que l’une des différences lors de l’utilisation de swipl-ld pour générer une DLL au lieu d’un fichier EXE est qu’il omet les lignes:

 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 

J’ai donc essayé de le faire manuellement, en remplaçant le nom aléatoire par “mystate.exe” et en utilisant la commande Win32 copy /b pour l’append à food.exe. Cela fait de food.exe une console de premier niveau sur laquelle je peux tester j’aime likes/2 . Est-ce parce que la Dll n’a pas de main() ? Quoi qu’il en soit, c’est le plus loin que je puisse obtenir pour le moment et j’imagine que l’argument qsave_program/2 secondes devait changer. J’ai essayé de remplacer toplevel=prolog par stand_alone=true . À propos, l’exemple de commande donné à la fin de ( http://www.swi-prolog.org/pldoc/doc_for?object=section%282,%272.10%27,swi%28%27/doc/Manual/ compilation.html% 27% 29% 29 ) ne génère aucun fichier. Quoi qu’il en soit, je ne peux pas savoir si et comment je dois le faire non plus.

Quelqu’un peut-il me dire comment résoudre ce problème?

Pardonnez-moi, car ce n’est pas vraiment une réponse précise à votre problème, mais un compte-rendu de mon expérience sur le sujet.

J’ai travaillé sur pqConsole , une DLL qui introduit les liaisons Qt via l’interface C ++.

pqConsole, qui est encore en développement, a réussi à se faufiler depuis le début , et j’ai eu la joie de travailler avec Jan Wielemaker pour faire grandir ce petit pas en avant pour l’audience de Prolog.

Je suggérerais de construire votre DLL avec G ++, afin d’obtenir une compatibilité binary, et de publier le (s) composant (s) SWI-Prolog tels quels.

Si vous aimez Qt, vous pouvez utiliser QtCreator pour la conception d’interface, voir par exemple fdqueens . Vous pouvez également voir comment j’avais l’habitude d’incorporer les ressources du projet .pl dans Qt, pour avoir plus de contrôle sur l’application (les utilisateurs ne peuvent pas jouer avec la logique Prolog requirejse depuis d’autres parties) et sur la version (pas d’ajout .pl , juste l’exécutable / DLL).

HTH

Résolu! Au cas où quelqu’un aurait besoin de la réponse un jour:

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

Ensuite:

 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.