DLL-PROLOG 6.0 - Details

DLL-PROLOG 6.0 is the latest version of LPA's true 32-bit Prolog compiler, and is available for all versions of Microsoft Windows, from Windows 98SE right up to Windows 8, and everything in-between. It shares its Prolog engine with WIN-PROLOG, and includes all the non-GUI specific predicates of the latter system. In actual feaure list, its closest relative in the 386-PROLOG family is CON-PROLOG, and differs from the latter in only two principal ways:

  • CON-PROLOG is a stand-alone executable program, designed to interact with the user through a classic Standard Input and Output (STDIO) consule
  • DLL-PROLOG has no native user input and output, and is designed to be embedded within and controlled by other applications who handle I/O on Prolog's behalf.

Because their feature sets are so close, and to avoid unnecessary duplication of information, please refer to the CON-PROLOG Details page for a complete run-down of DLL-PROLOG's features. The remainder of the present file is dedicated to explaining the API used by DLL-PROLOG.

Application-Supplied Input and Output

The key aspect of DLL-PROLOG, is that it defers all standard input and output to the host application: the host can do whatever it wants this I/O, including echoing it to the user, or simply using it for internal processing and further querying. Moreover, at the host application's chocie, this I/O may be peformed in 8-bit regular text (ISO/IEC 8859-1) encoding or 16-bit Windows Unicode (UTF-16LE). Internally, DLL-PROLOG supports the same full 32-bit character set as all the other BDS Prolog engines, but the API can be set up as desired to suit the application.

The DLL-PROLOG API

The entire API for DLL-PROLOG comprises a mere half dozen functions and notification codes. Let's get stuck in directly!

Result = InitProlog(Mode)

This function is used to initialise DLL-PROLOG, and must be called once per session, before any of the other functions are used. Its input parameter is simply a flag, which should be set to one of either "FALSE" (for ISO/IEC 8859-1 text) or "TRUE" (for UTF-16LE Windows Unicode). The function will return one of the following results:

Name Value Meaning
CMD_EXIT -1 Prolog session has finished (for example, one of halt/0 or exit/1 has been called)
CMD_INIT 0 Prolog session has already been initialised: use the remaining functions
[other] >0 The returned value is an LPSTR or LPWSTR pointer to a buffer (dependent on Mode) which will be used to return all output from the Prolog session

Note that "Windows Unicode" is effectively UTF-16LE, except in that it has no restrictions on illegal character values, and that it does not support or recognise surrogate pairs.

Result = CallProlog()

This is the function that excecutes DLL-PROLOG. In order keep the host application in control at all times, this function generally returns very quickly after being called. In reality, it executes up to a maximum of 256 resolution cycles of the Prolog engine, returning to the host when these have been performed, or sooner, if "user input" is required.

You should call this function repeatedly to execute Prolog, while checking the return code, which will be one of the following results:

Name Value Meaning
CMD_EXIT -1 Prolog session has finished (for example, one of halt/0 or exit/1 has been called); Prolog has placed the exit code, as text in the buffer returned by InitProlog(), in the requested mode (ISO/IEC 8859-1 or Windows Unicode): retrieve and process this NULL-terminated text if it is desired to know this exit code
CMD_INIT 0 Prolog session has not been initialised: call InitProlog() before proceeding further
CMD_SHOW 1 Prolog has placed some output in the buffer returned by InitProlog(), in the requested mode (ISO/IEC 8859-1 or Windows Unicode): retrieve and process this NULL-terminated text before calling CallProlog() again
CMD_PEEK 2 Prolog is just checking for break interrupts; call CallProlog() again to gnore, or StopProlog() to force a break
CMD_CHAR 3 Prolog wants a single character of input: call CharProlog() to provide it, or CallProlog() to ignore the request
CMD_TELL 4 Prolog wants a line of text input: call TellProlog() to provide it, or CallProlog() to ignore the request

Note that the return value from CallProlog() sets the "mode", which in turn determines which functions can be used successfully. In particular, CharProlog() and TellProlog() can be used only after CallProlog() CMD_CHAR or CMD_TELL returns respectively; the single exception to this is that TellProlog() can also be used directly after a successful call to InitProlog(), in order to set up an initial command line.

Result = CharProlog(Char)

If CallProlog() has returned a value of "CMD_CHAR", it indicates that the engine has invoked one of the direct key input predicates, such as getb/1, and is waiting for the "user" to "press a key". Calling CharProlog(Char) simulates this event, as if the user pressed a key whose value was the integer specified in the single "UCHAR" integer, "Char". The return result is one of the following:

Name Value Meaning
CMD_EXIT -1 Prolog session has finished (for example, one of halt/0 or exit/1 has been called)
FALSE 0 Character was not requested/accepted, or the interface is in the wrong mode
TRUE 1 Character was accepted

Result = TellProlog(Text)

If CallProlog() has returned a value of "CMD_TELL", it indicates that the engine has invoked one of the buffered console input predicates, such as eread/1, and is waiting for the "user" to "edit a line of input and then press enter". Calling TellProlog(TEXT) simulates this event, as if the user typed the text contained in the given LPSTR plain text(ISO/IEC 8859-1) or LPWSTR (Windows Unicode UTF-32LE) string, and then pressed "ENTER".

The text being passed to Prolog should be NULL-terminated, and in the format specified in the call to InitProlog(); not that a carriage return is automatically added to the end, does not have to included programmatically. The return result is one of the following:

Name Value Meaning
CMD_EXIT -1 Prolog session has finished (for example, one of halt/0 or exit/1 has been called)
FALSE 0 Text was not requested/accepted, was too too long to be stored completely, or the interface is in the wrong mode
TRUE 1 All characters were accepted, including an appended carriage return

Note that the input string is limited to 4094 characters, because the buffer is 8kb (8192) characters in size, and space must be allowed for an automatically appended return character and final NULL termination.

Result = StopProlog()

This function can be used any time CallProlog() returns during a running session, and simulates the "user" pressing "<CTRL><DEL>" keys together, to force a break interrupt. Subsequent calls to CallProlog() will most likely return "CMD_SHOW" requesting the display of text relating to the break, followed by "CMD_CHAR", indicating that a one-key reponse is desired.

Send a break signal to Prolog. The return result indicates the condition of the internal break flag, set by break/0, which in turn dictates whether or not the break will be acted upon imminently:

Name Value Meaning
CMD_EXIT -1 Prolog session has finished (for example, one of halt/0 or exit/1 has been called)
FALSE 0 Break flag is off, so break will not be acknowledged until break/1 is called with an argument of "1"
TRUE 1 Break flag is on, so break will be acknowledged imminently
Note that you will have to call CallProlog() one or more times in order to reach the point where the break is acknowleged.

Result = SendProlog(Window,Message,Data)

This function can be used any time CallProlog() returns during a running session, to send a "message" to Prolog, simulating the behaviour of Windows messages. All three parameters are arbitrary integers, which will be picked up by the main/4 predicate and dispatched in exactly the same way as a true message in WIN-PROLOG. The return value will be one of:

Name Value Meaning
CMD_EXIT -1 Prolog session has finished (for example, one of halt/0 or exit/1 has been called)
FALSE 0 Message not accepted: queue is full
TRUE 1 Message accepted and queued

Note that you will have to call CallProlog() one or more times in order to reach the point where the message is acknowleged.

Use of Windows Sockets (Winsock) Predicates

Along with nearly all the features CON-PROLOG, Windows Sockets (Winsock) predicates have been incorporated into the DLL. These predicates support TCP/IP network communications, and are identical to those in WIN-PROLOG, except that they are not supported by asynchronous messages. If is is desired to use these predicates, the host application is responsible for calling WSAStartup() before and WSACleanup() after any such use. If the Winsock predicates are not to be used, then no such calls are necessary.

Implementing an Interactive Prolog System

To show how easy it is to use the DLL-PROLOG API, here is some pseudocode to create an interactive Prolog stem, perhaps resembling CON-PROLOG:

    /* Initialise in 8-bit text mode */

    Code = InitProlog(FALSE) ;

    if      Code == CMD_EXIT
    then    QUIT with "already run and finished" error
    else if Code == CMD_INIT
    then    WARN "already initialised" and continue
    else    SAVE "Code" as Memory Buffer Address, in variable, "Text"

    /* run till done */

    repeat
        Code = CallProlog()
            if      Code == CMD_SHOW
            then    DISPLAY Text (memory buffer address) on screen
            else if Code == CMD_CHAR
            then    GET BYTE from user, and call CharProlog(Byte)
            else if Code == CMD_TELL
            then    READ LINE from user, and call TellProlog(Line)
    until Code = CMD_EXIT

    /* tidy up and go home */

An actual source code example of the above, written in C and called PRO386X, is shipped with DLL-PROLOG, and implements a look-alike of CON-PROLOG, using DLL-PROLOG to perform all the hard work. Similar examples can be put together in minutes to exploit DLL-PROLOG with great ease.