Also to Arne Skjærholt for the 64-Bit version (SwiPlCs64.dll) and Batu Akan for the Mono code. Foutelet Joel provide the F# sample.
Here is the link to download the latest binaries or older versions.
Download page
There is also a copy on SWI-Prolog Twiki page
and SWI-Prolog contrib page. The latter might be outdated.
At present I only publish the binaries including the documentation.
The sources, which are now under LGPL 2, might be published later.
If you like to see them or work on them don't hesitate to contact me via mail.
The latest version work with SWI-Prolog 6.3.1 and higher.
The AssemblyVersion number, e.g. 1.1.60601.0, can be interpreted as follows:- 1 - major version
- 1 - minor version
- 60601 - SWI-Prolog version 6.6.1 (test cases run against this prolog version)
- 0 - patch level version
Copy SwiPlCs.dll or SwiPlCs64.dll and SwiPlCs.XML where ever you want and add a project reference to SwiPlCs.dll.
After that IntelliSense and tool tips should be available.
Make sure that libswipl.dll and its dependencies could be found by the system. For the sample below it is: libswipl.dll, pthreadGC2.dll, libgmp-10.dll, files.dll For a big application it could be a lot more.
TIP: For development add the SWI-prolog bin directory to the PATH environment variable.
NOTE: Don't forget to restart Visual Studio after that. VS must recognize the new environment
for debugging.
Basically windows search first in the folder where the executable resist than in the windows system directory and at least in the directories that are listed in the PATH environment variable. For details see "Dynamic-Link Library Search Order"
If libswipl.dll or one of its dependencies could not found you will recive an error like
System.IO.FileNotFoundException: Das angegebene Modul wurde nicht gefunden. (Ausnahme von HRESULT: 0x8007007E)
An other common error is:
SWI-Prolog: [FATAL ERROR:
Could not find system resources]
Failed to release stacks
To fix this add the SWI_HOME_DIR environment variable as described in
SWI-Prolog FAQ FindResources
with a statment like this befor calling PlEngine.Initialize.
Environment.SetEnvironmentVariable("SWI_HOME_DIR", @"the_PATH_to_boot32.prc");
A sample says more then I want to write here.
using System; using SbsSW.SwiPlCs; namespace HelloWorldDemo { class Program { static void Main(string[] args) { //Environment.SetEnvironmentVariable("SWI_HOME_DIR", @"the_PATH_to_boot32.prc"); if (!PlEngine.IsInitialized) { String[] param = { "-q" }; // suppressing informational and banner messages PlEngine.Initialize(param); PlQuery.PlCall("assert(father(martin, inka))"); PlQuery.PlCall("assert(father(uwe, gloria))"); PlQuery.PlCall("assert(father(uwe, melanie))"); PlQuery.PlCall("assert(father(uwe, ayala))"); using (PlQuery q = new PlQuery("father(P, C), atomic_list_concat([P,' is_father_of ',C], L)")) { foreach (PlQueryVariables v in q.SolutionVariables) Console.WriteLine(v["L"].ToString()); Console.WriteLine("all children from uwe:"); q.Variables["P"].Unify("uwe"); foreach (PlQueryVariables v in q.SolutionVariables) Console.WriteLine(v["C"].ToString()); } PlEngine.PlCleanup(); Console.WriteLine("finshed!"); } } } }
Here is how to use the library in F#. Manny thanks to Foutelet Joel for this sample.
// Learn more about F# at http://fsharp.net open System open SbsSW.SwiPlCs; let ple = PlEngine.IsInitialized in if ple then printfn "Echec initialisation" else begin PlEngine.Initialize([|"-q"|]) PlQuery.PlCall("assert(father(martin, inka))") |> ignore PlQuery.PlCall("assert(father(uwe, gloria))") |> ignore PlQuery.PlCall("assert(father(uwe, melanie))") |> ignore PlQuery.PlCall("assert(father(uwe, ayala))") |> ignore let q = new PlQuery "father(P, C), atomic_list_concat([P,'is_father_of ',C], L)" in begin Seq.iter (fun (x : PlQueryVariables) -> printfn "%A" (x.Item("L").Name)) q.SolutionVariables printfn "all children from uwe:" let r : PlQueryVariables = q.Variables in r.Item("P").Unify("uwe") |> ignore Seq.iter (fun (x : PlQueryVariables) -> printfn "%A" (x.Item("C").Name)) q.SolutionVariables end PlEngine.PlCleanup() printfn "%A" "finished!" end
For further samples see the examples in SbsSW.SwiPlCs and SbsSW.SwiPlCs.PlEngine.
The class SbsSW.SwiPlCs.PlQuery is the key to ask SWI-Prolog for proofs or solutions.
The SbsSW.SwiPlCs.PlTerm
I strongly recomanate to use SbsSW.SwiPlCs.PlQuery in a using statment using statment like in the sample program above.
An alternitive is to call Dispose explicitly like in the sample below.
const string strRef = "a;e;"; PlQuery.PlCall("assert(n('" + strRef + "'))"); var q = new PlQuery("n(X)"); Assert.IsTrue(q.NextSolution()); Assert.AreEqual(strRef, q.Variables["X"].ToString()); var q2 = new PlQuery("n('" + strRef + "')"); Assert.IsTrue(q2.NextSolution()); Assert.AreEqual(strRef, q.Variables["X"].ToString()); q2.Dispose(); q.Dispose();
Note that access to the query Variables is impossible after Dispose().
SbsSW.SwiPlCs.PlEngine.Initialize work *not* as expected if there are e.g. German umlauts in the parameters
e.g. in the path or filename for a qlf file ( switch -x )
See marshalling in the source NativeMethods.cs