在 dll 中嵌入 prolog 引擎

Embedding prolog engine in a dll

本文关键字:prolog 引擎 dll      更新时间:2023-10-16

我最近一直在开发一个嵌入prolog推理引擎的C++应用程序,正如标题中所述,我现在正在尝试生成一个DLL而不是可执行文件,以便我可以在另一个项目中使用它。由于我是 DLL 开发的新手,我想我可以从一个小例子开始。我有 3 个文件:

  • likes.pl:定义谓词 likes 的示例 prolog 文件/2
  • likes.cpp:定义调用PlQuery并在std::string中返回结果的函数get_food()
  • 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()只返回一个字符串而不调用 prolog 时,这工作正常。但是,经过两天的调查,我不知道如何让DLL调用prolog。我认为我可能做错了两件事,也许两者都做错了:PlEngine 初始化和保存状态。

我已经尝试在get_food()food.cpp main()函数中调用 PlEngine,结果相同。所以现在我坚持第一个选项,因为我更感兴趣的是在 DLL 中完成所有操作。我在这里看到(在dll中嵌入SWI-Prolog)以后可以在DllMain中完成,但不建议这样做。最好的方法是什么?我应该给食物.exe作为argv[0]还是其他东西(libswipl.dll?保存状态?)

其次,我注意到使用 swipl-ld 而不是 EXE 生成 DLL 时的一个区别是它省略了以下行:

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。这使得食物.exe成为我可以测试likes/2的顶级控制台。是因为 Dll 没有任何main()吗?无论如何,这是我目前能得到的最远的,我想在第二个论点qsave_program/2有一些事情需要改变。我尝试用stand_alone=true替换toplevel=prolog.顺便说一下,(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,这是一个通过C++接口引入Qt绑定的DLL。

pqConsole虽然仍在开发中,但到目前为止已经找到了自己的方式,我很高兴与Jan Wielemaker合作,为Prolog受众的扩大迈出了这一小步。

我建议使用 G++ 构建您的 DLL,以获得二进制兼容性,并按原样发布 SWI-Prolog 组件。

如果你喜欢Qt,你可以使用QtCreator进行界面设计,例如参见fdqueens。在那里,您还可以看到我过去如何在Qt项目资源中嵌入.pl,以便更好地控制应用程序(用户不能弄乱其他部分所需的Prolog逻辑)和版本(无需添加.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 initn" ;
    else
        cout << "OK initn" ;
    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.