News: New edition of the SWI-Prolog manual as bookSearch Documentation:
SWI-Prolog owl logoSWI-Prolog 2-Way interface to .NET/Mono


This is an overview of an interface which allows SWI-Prolog programs to dynamically create and manipulate .NET objects.

Here are some significant features of the interface and its implementation:

  • API is similar to that of XPCE: the four main interface calls are cli_new, cli_call, cli_set and cli_get (there is a single cli_free, though .NET's garbage collection is extended transparently into Prolog)
  • Uses @/1 to construct representations of certain .NET values; if @/1 is defined as a prefix operator (as used by XPCE), then you can write @false, @true, @null, @void etc. in your source code; otherwise (and for portability) you'll have to write e.g. '@'(true) etc.
  • cli_call/4 (modeled from JPL's jpl_call/4) resolves overloaded methods automatically and dynamically, inferring the types of the call's actual parameters, and identifying the most specific of the applicable method implementations (similarly, cli_new resolves overloaded constructors)
  • Completely dynamic: no precompilation is required to manipulate any .NET classes which can be found at run time, and any objects which can be instantiated from them
  • Interoperable with Uwe Lesta's SwiPlCS's .NET API.
  • Autoloads (defines) new prolog preds marked with [PrologVisible] in your DLLs - supporting you coding nondeterministic and deterministic versions.
  • Exploits the Invocation API of the .NET P/Invoke Interface: this is a mandatory feature of any compliant .NET
  • Implemented with a fair amount of C# code and Prolog code in one module ( (which I believe to be ISO Standard Prolog compliant and portable) and a SWI-Prolog-specific foreign library (swicli[32].dll for Windows and swicli[32].so *nix), implemented in ANSI C but making a lot of use of the SWI-Prolog Foreign Language Interface Then uses Swicli.Library.dll (Managed binary) that runs on both Mono and .NET runtimes.
  • the Prolog-calls-CLI (mine) and CLI-calls-Prolog (Ewe's) parts of SWICLI are largely independent; mine concentrates on representing all .NET data values and objects within Prolog, and supporting manipulation of objects; Ewe's concentrates on representing any Prolog term within .NET, and supporting the calling of goals within Prolog and the retrieving of results back into .NET
  • @(terms) are canonical (two references are ==/2 equal if-and-only-if they refer to the same object within the .NET)
  • are represented as structures containing a distinctive atom so as to exploit SWI-Prolog's atom garbage collection: when an object reference is garbage-collected in Prolog, the .NET garbage collector is informed, so there is sound and complete overall garbage collection of .NET objects within the combined Prolog+.NET system
  • .NET class methods can be called by name: SWICLI invisibly fetches (and caches) essential details of method invocation, exploiting .NET Reflection facilities
  • Reason about the types of .NET data values, object references, fields and methods: SWICLI supports a canonical representation of all .NET types as structured terms (e.g. array(array(byte))) and also as atomic .NET signatures
  • when called from Prolog, void methods return a @(void) value (which is distinct from all other SWICLI values and references)
  • Tested on Windows XP, Windows7 and Fedora Linux, but is believed to be readily portable to SWI-Prolog on other platforms as far as is feasible, .NET data values and object references are represented within Prolog canonically and without loss of information (minor exceptions: .NET float and double values are both converted to Prolog float values; .NET byte, char, short, int and long values are all converted to Prolog integer values; the type distinctions which are lost are normally of no significance)
  • Requires .NET 2.0 and class libraries (although it doesn't depend on any .NET 2-specific facilities, and originally was developed for use with both 1.0 thru 4.0 .NETs, I haven't tested it with 1.0 recently, and don't support this)


?- use_module(library(swicli)).

?- cliCall('System.Threading.ThreadPool','GetAvailableThreads'(X,Y),_).

X=499, Y=1000

Doc root will be findable from

- Douglas Miles
See also
- CSharp.txt