Systems programming using Prolog (aka uniform and well supported FFI)

Hello Prolog Implementers,

It is surprisingly difficult to write (useful) desktop or server applications using common subset of Prolog (aka ISO Prolog) without commiting to a single implementation. Which is in part caused by the absolute lack of any libc functionallity, like UNIX IPC (semaphores, pipes, message queues, shared memory, signals), timers, DNS name resolution, I/O multiplexing via select() or poll(), etc, etc; and complete inability to dlopen() pre-compiled library – basically the only way is to write a small binary that does “system stuff” and then communicate with a Prolog process via an ad-hoc protocol for example using pipes. This approach works (I use it in my projects), but it is very limiting.

Is there any chance of a standard FFI mechanisms that might be accepted across different implementations? Web-based Prolog systems are naturally out of scope. My main interest is using Prolog in embedded Linux environments.

I think that a good, generic and universally accepted FFI mechanism is much better than for example custom HTTP support, even if API is largely the same.

Alternatively an easier ask would be to let all Prolog systems at least to expose file descriptors to the user program. This will allow programmers to overcome a lot of missing libraries using “chain-loading” in a similar fasion to xinetd, so one program handles connection establishment and then exec()s into Prolog process, so it inherits a pre-connected file descriptor that can be internally bound to a stream. Currently it is possible with stdin/stdout, but that’s too limiting.

Indeed such inversion is a valid approach, but currently it requires ethier to commit to a single Prolog implemention (like SWI, GNU, whatever) or write an abstraction level in C – which is a task, so full of underwater rocks that I don’t really want to go that way.

As a I said I already embrace 2 process solution: first is a small app in C that does some low-level stuf and second is Prolog process that uses standard streams to communicate with it. But I can’t go very far with that approach, because it isn’t really possible to serialize everything and it needs a lot of conceptualization upfront.

For example my latest project uses GitHub - NXPNFCLinux/linux_libnfc-nci: Linux NFC stack for NCI based NXP NFC Controllers · GitHub, so I have a small C app that converts communication with a smart card to a plain read/write on stdin/stdout. And then I have a Prolog runtime that implements the logic.

Is it a good approach? idk, but that’s the only way that works reliably accross a large collection of Prolog systems.

Yeah one way forward could be, just create your comms library in C first.

                     +------------+              +-------------+
                     | Comms      | IPC          |  Smart      |
                     | Library    |<------------>|  Card       |
                     |            |              |             |
                     +------------+              +-------------+

And then provide a Prolog bindings via FFI for your Prolog of choice:

+------------+       +------------+              +-------------+
|  Your      | ABI   | Comms      | IPC          |  Smart      |
|  Prolog    |<----->| Library    |<------------>|  Card       |
|            |       |            |              |             |
+------------+       +------------+              +-------------+

In rare cases you find an existing comms library that has already a Prolog
binding for a particular Prolog. Or that it would be easy to make a Prolog
binding. I doubt that Prolog systems have some generic approach that

covers all cases. I even doubt libc has that. Usually libc only offers
some logical layer that abstracts the physical layer. The transport
layer with formats and protocolls, is yet another kettle. And then you

will provide your own application view, which is again another layer.
Problem can appear if you dont have a comms library only a comms
application. But we live in an agentic world, I even heard people praising

Prolog for hooking into keyboard events and then reading a payment
terminal as a quick and dirty, but yet useful solution. You could claim
JSON is just keyboard events in disguise creating an unnessary

“interlingua”. The agentic future could be even decoding error message
and what ever text comes along, using strings/3 in reverse mode. So
I whole heartely suggest a library “input”. While PIP “format” is what

printf is for C, the complementing PIP “input” would be what scanf is for C:

  • PIP input
    The reverse of format

If one doesn’t want to go DCG on stdin, this could be your swiss knife.

Project maybe dead, but it is the only that I found that works with this dongle, so that’s good to me.

For me 2 process solutions works ok, but I started this thread because real FFI would’ve been much better.

For example that library has a bug and it hangs on shutdown when USB dongle was removed unexpectedly. I have a very easy workaround in C: I just call alarm() just before shutdown – this is literaly impossible to do in Prolog. Because no implementation supports signals and timers.

I don’t know how you use alarm() in your application, that
gives you some solution to some problem. But I wonder what
you mean by “no implementation”. SWI-Prolog has a very

huge collection of system libraries. For example I find:

library(time): Time and alarm library
https://www.swi-prolog.org/pldoc/man?section=time

Often the motivation to introduce alarms in a Prolog system
is to ultimately have a predicate call_with_time_limit/2.
And while alarm() delivers a SIGALRM to the application,

one of the challenges can be to use a softer method, especially
a method that works together with Prolog’s setup_call_cleanup/3,
so that resources get unlocked in a graceful way, where ever

the Prolog code was interrupted. Equivalents of alarm() are also
found in libuv. To do these things graceful, can also involve thinking
about stackfull and stackless coroutines, especially when you want

Prolog code to do some short event handling work when an alarm
gets triggered. I understand that you want to somehow reduce the
world to libc. But I wonder whether the world is just much bigger

than you think. For example SWI-Prolohg is not the only Prolog
system that ultimately supports call_with_time_limit/2, but yet
there is also no PIP for that. So we could suggest as well:

  • PIP alarm:
    Stuff like call_with_time_limit/2 and friends

Again most my PIP suggestions collect what is already around.
Like memory and alarm would collect what is already around, while
input is more speculative, not sure whether dcg/basics, also found in

a couple of Prolog systems around the world would count for it.

That’s the point – I don’t want to do it gracefully. There is a bug in a lib and I have to kill my app if it doesn’t shutdown in 10 sec. Here is code.

My assumption was when you can do it gracefully,
you can also do it more harder. Its all a matter whether
you allow general signal handlers or not. Try this:

?- alarm(10, halt).

The problem I see, for a Prolog system design, if your
Prolog system cannot do gracefull alarms, there is no
going back to gracefull alarms. But if your Prolog system

can do gracefull alarms, you can still go back to non-
gracefull alarms. Disclaimer I dunno whether alarm+halt
in SWI-Prolog has enough force. Interestingly halt/0

respectively halt/1 made it even into the ISO standard:

hal(+Status) [ISO]
https://www.swi-prolog.org/pldoc/doc_for?object=halt/1

But the more splendid solution could be libuv and
shutdown handlers, or who knows what. Orthogonal
to that could be also concepts like task groups, and

managing their life cycle via structured concurrency.
Although event oriented solutions often lack a little bit
the parenthesis of a structured concurrency construct,

the whole application is one big parenthesis?

1 Like

Also thanks about the pointers, I didn’t know about library(time).

UPD: But this kinda misses the point, I want to write portable Prolog, as I said in the begining. I know that it is possible to do system level programming in some prologs, but I want to be able to do this without having to commit to a single implementation – like SWI.

You could use the GNU Prolog FFI:

10.3 Calling C from Prolog
http://www.gprolog.org/manual/html_node/gprolog068.html

Its quite portable. You can build it from source. But its a much
smaller Prolog system than SWI-Prolog. For example it doesn’t
have biginteger nor unicode. Then adding alarm() to GNU

Prolog is possibly something along the lines:

:- foreign(alarm(+positive)).

Further while building GNU Prolog link it with your alarm stub
implementation. Your alarm stub implementation should use the
C declarations from <gprolog.h> to have return types and formal

parameters that conform to the GNU Prolog FFI conventions.