2
votes

I'm building a C++ library (windows, DLL) and I'd like to embed swi-prolog for some functionalities.
What I'm doing is:

#include <Windows.h>
#include <SWI-Prolog.h>

BOOL WINAPI DllMain(
    HINSTANCE hinstDLL,  // DLL モジュールのハンドル
    DWORD fdwReason,     // 関数を呼び出す理由
    LPVOID lpvReserved   // 予約済み
)
{
    BOOL result = TRUE;

    switch(fdwReason)
    {
        case DLL_PROCESS_ATTACH:
        {
            char* av[]{"libswipl.dll"};

            _putenv(R"(SWI_HOME_DIR=C:\Program Files (x86)\swipl\)");

            if(!PL_initialise(1, av))
            {
                result = TRUE;
            }
            else
            {
                PL_halt(1);
                result = FALSE;
            }

            break;
        }

        case DLL_PROCESS_DETACH:
        {
            result = PL_cleanup(1);
            break;
        }
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
            break;
    }

    return result;
}

and including "libswipl.lib", renamed from "swipl\lib\libswipl.dll.a".

First it gives errors because of missing dll, so I copied those in my executable folder until it was happy (specifically, libswipl.dll;libgmp-10.dll;pthreadGC2.dll).

I don't need to include a pl file into the executable (is this what swipl-ld does?) because I would like to add facts and rules dinamically by code later, so it's ok to initialize with a clear state.

What I'd like to know is, how do I get rid of the dependencies (SWI_HOME_DIR) and make it stand-alone?

2
??? ...including "libswipl.lib", renamed from "swipl\lib\libswipl.dll.a". ???CapelliC
well, the documentation says to include the lib file associated to the dll, but I couldn't find any. My lib contents (fresh install) are "jpl.jar", "libpthreadGC2.dll.a", "libswipl.dll.a" and "plterm.dll.a". Even searching, the whole swipl folder does not contain a single lib file.キキジキ
You can create a lib from a dll (or here), but if you used the wrong lib file, you would get linker errors. So I think the file you renamed was the right one.wimh
It's no clear to me what build tools you are using. Windows builds require MinGW.CapelliC
according to this doc there is no need to rename the dll.a to libCapelliC

2 Answers

0
votes

I have never used SWI-Prolog, but looking at the installed files, some of the files installed there seem to be required to run the prolog engine.

If you mean you want to embed everything into your dll, it would probably not be possible, the only way would be modifying swi-prolog itself. But that won't be easy.

If you just don't want to require swi-prolog to be installed to have your program running. you can create your own installer which included all files to run swi-prolog, and include it in your own (sub)directory. You still need to set SWI_HOME_DIR, but you will know the relative directory to your executable.

If you don't want to use _putenv to set SWI_HOME_DIR, you can also set SWI_HOME_DIR in the windows system settings to the correct value.

1
votes

First I would not recommend to initialize prolog in the DllMain, pls see here:

But, you could still use it and check if dependent libraries are there, not only libswipl.dll which changed to swipl.dll from the version 5.10, but also:

  • pthreadVC2.dll for 64 bits or pthreadVC.dll for 32 bits
  • plterm.dll (optional, terminal emulation)

Then, I would add and export a function to initialize prolog, and set required parameters (like: saved-state filename or boot32.prc/boot64.prc, flags e tc).

And, you dont need SWI_HOME_DIR when you pass all required parameters to your PL_initialise function.

Also, in case of MultiThreaded environment, these calls are required: PL_thread_attach_engine and PL_thread_destroy_engine.

More on the topic is here: swi-prolog

Cheers!