# Swi-prolog bindings to SDL

**URL:** <https://swi-prolog.discourse.group/t/swi-prolog-bindings-to-sdl/7610>\
**Category:** General\
**Created:** [July 20, 2024, 12:49pm UTC](https://swi-prolog.discourse.group/t/swi-prolog-bindings-to-sdl/7610 "2024-07-20T12:49:49Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![kwon-young](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/kwon-young/32/4841_2.png) [@kwon-young](https://swi-prolog.discourse.group/u/kwon-young)\
**Post date:** [July 20, 2024, 12:49pm UTC](https://swi-prolog.discourse.group/t/swi-prolog-bindings-to-sdl/7610/1 "2024-07-20T12:49:49Z")

</div>

Hello all,  
I have started to make swi-prolog bindings to the C multimedia library SDL: [GitHub - kwon-young/sdlpl: SWI-Prolog bindings to SDL](https://github.com/kwon-young/sdlpl)  
For now, I have used the C Foreign Language Interface documented here: [SWI-Prolog -- Foreign Language Interface](https://www.swi-prolog.org/pldoc/man?section=foreign)  
Here is my experience and a few questions for those of you that are more knowledgeable than me:

- Should I be using the C++ interface instead ? @peter.ludemann mentionned to me privately that using C++ simplifies error handling. I did not have the time to read the C++ interface documentation yet…
- How should I hande foreign data ? SDL functions can returns handles to things like surfaces or textures that should be freed **in order**. `setup_call_cleanup` is great when knowing the lifetime of the handle beforehand (like the handle for a window) but not great when dealing with textures that can be freed anytime. I tried to use Blobs but I don’t think we can impose freeing order on them (like all image textures should be freed before doing `image_quit`.
- How should I handle C flags arguments ? For now, I’m converting prolog atoms to integers and ORing them in prolog for readability. Is there a better solution ?

As a more general question, is anyboy interested on colaborating on this project ?  
How about we write small reference games with it like a pong or snake ?  
Or a small immediate mode gui framework for visualising things like clpfd constraints labelling (sudoku or n-queens) ?  
Or a gui framework like QML (in the C++ Qt) world where we can declaratively specifiy the gui in a dict ?

---

<div class="post-metadata">

**Author:** ![maren](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/maren/32/6605_2.png) [@maren](https://swi-prolog.discourse.group/u/maren)\
**Post date:** [July 20, 2024, 6:18pm UTC](https://swi-prolog.discourse.group/t/swi-prolog-bindings-to-sdl/7610/2 "2024-07-20T18:18:23Z")

</div>

Regarding cleanup, maybe you can use state blobs that carry everything, including the order of allocation, and then just define predicates that work with those state blobs, rather than have everything as separate blobs.  
That way you retain full control over the cleanup.

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [July 20, 2024, 6:34pm UTC](https://swi-prolog.discourse.group/t/swi-prolog-bindings-to-sdl/7610/3 "2024-07-20T18:34:14Z")

</div>

I recommend using SWI-cpp2.h (as documented in [SWI-Prolog -- A C++ interface to SWI-Prolog (Version 2)](https://www.swi-prolog.org/pldoc/man?section=cpp2)), even if you’re interfacing to C code. The following assumes that you’re writing foreign predicates, which is the most common use case (there are some more complex situations, such as calling Prolog from C/C++; SWI-cpp2.h is also better for this but some things require more care, especially C++ exceptions)

Off the top of my head, these are the advantages of using the C++ API (I’ll edit this list if more things occur to me in the future):

- It’s efficient – the C++ wrapper classes (`PlTerm`, `PlAtom`, etc.) are the same size as the underlying `term_t`, `atom_t`, etc. types, which can be efficiently accessed using `unwrap()` if needed.
- Most of the C functions that manipulate `char*` data have corresponding C++ methods that use `std::string`, which simplifies memory management.
- Simplified error handling – most of the `PL_*()` functions (in `SWI-Prolog.h`) have corresponding `Plx_*()` functions that check for an error and throw a C++ exception if needed.
  - The `PREDICATE` declaration takes care of handling the C++ exception and turning it into a Prolog error.

- Simplified unification failure handling – you can throw `PlFail` or wrap a call with `PlCheckFail()` to short-circuit when unification fails.
- Convenience functions for creating an error term and raising an error in Prolog.
- You can always get at the underling `term_t`, `atom_t`, etc. by using the `unwrap()` method, so everything in the `SWI-Prolog.h` API is available if needed.
- It’s easy to create a “blob”, which is probably how you should wrap foreign data: [SWI-Prolog -- Blobs](https://www.swi-prolog.org/pldoc/man?section=cpp2-blobs) (the C++ API for blobs isn’t completely general, but it should cover 99% of cases).
- You can take advantage of C++ features such as “smart pointers” (e.g. `std::unique_ptr`) and `std::string`.
- The code for non-deterministic foreign predicates and the “context” is simpler and less error-prone – there is sample code in the documentation and in the test cases.
- If you’re handling connections to a file system or database, there is a utility module for mapping atoms to Prolog terms (including blobs).

There are some negatives:

- In some situations, it’s slightly less efficient than the C API.
- C++ compilation tends to be slower than C compilation and compilation error messages can sometimes be difficult to understand.
- If you’re a C programmer and not familiar with C++, there can be some tricky bits. I can do code reviews or give advice. 🙂
- The C++ memory model doesn’t fit well with the Prolog memory model (this is also true with C, of course), so sometimes the code becomes more complicated because of that. However, there are convenience classes and functions that help deal with the mismatch (`PlTermScoped`, `unify_blob()`, `PlControl`).

> [@kwon-young](#):
>
> SDL functions can returns handles to things like surfaces or textures that should be freed **in order**.

Possibly this can be handled using C++ `std::shared_ptr`, which is essentially a reference-counted pointer, so you can “chain” the structures and their pointers. Depending on the situation, `std::unique_ptr` could also be used if there is “single ownership”.

But in general, blobs can be freed / garbage-collected at any time – would it make sense to put all your data into one large “blob” whose contents you free in proper order?

> [@kwon-young](#):
>
> How should I handle C flags arguments ?

Perhaps you can use [PL\_scan\_options()](https://www.swi-prolog.org/pldoc/man?CAPI=PL_scan_options) – there’s sample code in the documentation. Alternatively, there is ample code for handling a list of options. (If you’re talking about command-line options, there is also example code.)

---

<div class="post-metadata">

**Author:** ![kwon-young](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/kwon-young/32/4841_2.png) [@kwon-young](https://swi-prolog.discourse.group/u/kwon-young)\
**Post date:** [July 20, 2024, 7:26pm UTC](https://swi-prolog.discourse.group/t/swi-prolog-bindings-to-sdl/7610/4 "2024-07-20T19:26:43Z")

</div>

> [@peter.ludemann](#):
>
> would it make sense to put all your data into one large “blob” whose contents you free in proper order?

> [@maren](#):
>
> maybe you can use state blobs that carry everything

You both proposed the same idea but I don’t understand how would this work.  
With SDL, you can create resources like windows, renderers, surfaces or textures using function calls and SDL basically gives you an opaque pointer as handle to the resource.  
These handles have to be freed in order.  
Could one of you show an example of how I could pack all this into a single blob ?

---

<div class="post-metadata">

**Author:** ![maren](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/maren/32/6605_2.png) [@maren](https://swi-prolog.discourse.group/u/maren)\
**Post date:** [July 20, 2024, 7:36pm UTC](https://swi-prolog.discourse.group/t/swi-prolog-bindings-to-sdl/7610/5 "2024-07-20T19:36:20Z")

</div>

My c is incredibly rusty, so I can’t just quickly write a n actual example.

But the idea would roughly be as follows.

#### create a state blob object

This would be your global entrypoint. You’d define predicates like

```prolog
sdl_new_context(Ctx, ...)
sdl_free_context(Ctx, ...)

```

(though you can make garbage collection handle the free too, or do both).

Ctx would be your state object, returned as a blob in prolog.

#### create methods on this state blob object

things like

```prolog
sdl_new_window(Ctx, WindowHandle, ...)
sdl_new_bitmap(Ctx, BitmapHandle, ...)

```

and

```prolog
sdl_free_window(Ctx, WindowHandle, ...)
sdl_free_bitmap(Ctx, BitmapHandle, ...)

```

I don’t actually know what sdl does, so hopefully those are suggestive.

The handles could be anything, you could just return an atom, or a string, or whatever. it would be the responsibility of the ctx object to actually resolve them.

#### doing things with objects

```prolog
sdl_window_size(Ctx, WindowHandle, 800,600)
sdl_window_show(Ctx, WindowHandle)

```

On the C/C++ side, you’d implement these predicates by keeping around a mapping between your handles and the actual objects, then doing the internal appropriate c/c++ function on that.

[edit]  
I realize I left some things undiscussed. The point was making sure that freeing happens in order.  
Essentially, when doing something like  
`sdl_free_window(Ctx, WindowHandle)`  
You’d have an opportunity to make sure that the window is actually in a position to be freed directly, or if other stuff needs to happen first. Then you could either error (making a prolog library fix their mistake), or cascade the free. You are able to do this for each free method cause you always have the entire context available to you through the context object.

Note that if there’s only one global context ever, you don’t even need a ctx object, and you could directly work with predicates passing around handles. This is how XPCE does it.

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [July 20, 2024, 10:28pm UTC](https://swi-prolog.discourse.group/t/swi-prolog-bindings-to-sdl/7610/6 "2024-07-20T22:28:36Z")

</div>

I noticed that SDL has Python bindings, so you might be better off just using those via SWI-Prolog’s [Python interface](https://www.swi-prolog.org/pldoc/doc_for?object=section(%27packages/janus.html%27)). If not using Python, the question is: how does Python handle the problem of garbage collection? The Cpython implementation uses reference counting plus a garbage collector for circular references. This probably could be emulated by C++ `shared_ptr`, which is a reference counter (whether you could do this with a custom deleter or would need to implement something similar, I don’t know.

Another possibility is to have a blob for every SDL object, using `PlBlob::register_ref()` and `PlBlob::unregister_ref` (which use `PL_register_atom()` and `PL_unregister_atom()`) to maintain reference counts. You’d have to ask @jan if it’s guaranteed that the blob is deleted when the reference count goes to zero, and whether the deletions are done in order.

I don’t have time to learn the SDL API, so perhaps some sample code showing how the objects are created and destroyed would help me to suggest a solution.

---

<div class="post-metadata">

**Author:** ![maren](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/maren/32/6605_2.png) [@maren](https://swi-prolog.discourse.group/u/maren)\
**Post date:** [July 20, 2024, 10:43pm UTC](https://swi-prolog.discourse.group/t/swi-prolog-bindings-to-sdl/7610/7 "2024-07-20T22:43:21Z")

</div>

> [@peter.ludemann](#):
>
> Another possibility is to have a blob for every SDL object, using `PlBlob::register_ref()` and `PlBlob::unregister_ref` (which use `PL_register_atom()` and `PL_unregister_atom()`) to maintain reference counts. You’d have to ask @jan if it’s guaranteed that the blob is deleted when the reference count goes to zero, and whether the deletions are done in order.

This does not happen immediately when refcount becomes zero. There’s some conditions (such as use on stacks) where an atom still needs to be counted, so it is up to garbage collection to make the final call here.  
That also means you won’t have guarantees about order of frees if you do it that way. The garbage collection will just see a bunch of atoms/blobs as ‘freeable’ and act accordingly.  
Maybe some order can be forced here, where one type is always freed before the other, but that’s asking for trouble. Better to make the free order explicit in your code.

That said, returning individual objects as blobs can help you, cause it gives you a callback when the object is ‘freed’, which you are free to implement in any way you like, including doing some bookkeeping in a context object (and freeing/not freeing things according to that bookkeeping).

---

<div class="post-metadata">

**Author:** ![kwon-young](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/kwon-young/32/4841_2.png) [@kwon-young](https://swi-prolog.discourse.group/u/kwon-young)\
**Post date:** [July 21, 2024, 8:12am UTC](https://swi-prolog.discourse.group/t/swi-prolog-bindings-to-sdl/7610/8 "2024-07-21T08:12:25Z")

</div>

Thank you all for your examples and advices on using a state blob. I think I understand now.  
For now, I’m just going to pass pointers around and let future me decide what to do  
@peter.ludemann What is the canonical way to return a compound from C++ to prolog ?  
I want to use compound term to represent input events from SDL, things like `quit(Timestamp)` or `mousemotion(Timestamp, X, Y)`.  
Using a dict here would be ideal, but again, don’t know if this is possible ?

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [July 21, 2024, 3:35pm UTC](https://swi-prolog.discourse.group/t/swi-prolog-bindings-to-sdl/7610/9 "2024-07-21T15:35:05Z")

</div>

> [@kwon-young](#):
>
> What is the canonical way to return a compound from C++ to prolog ?

If you don’t care about the contents, use a blob. You can also provide “access” predicates for getting at the values in the blob, but that can become tedious to write. (There isn’t a good example in `test_cpp.cpp`, but I can easily write an example if you wish.)

If you do care about the contents, a dict would probably be a good way of handling a large structure; however, the only public function for dicts is `PL_get_dict_key()` (which is also available in `SWI-cpp2.h` as `Plx_get_dict_key()`. Perhaps this is an oversight, @jan?

In the absence of direct manipulation of dicts, you can easily create a term with whatever arity you wish and return that to Prolog, which converts it to a dict, e.g.

```prolog
SDL_complex_thing(c(A,B,C,D)),
Dict = c{a:A,b:B,c:C,d:D}

```

where `SDL_complex_thing/1` is a foreign predicate that’s something like this (untested code):

```cpp
PREDICATE(SDL_complex_thing,1)
{ auto result = call_SDL_thing(...);
  return A1.unify_term(PlCompound("c",
    PlTermv(PlTerm(PlTerm_integer(result.a),
                   PlTerm_string(result.b),
                   PlTerm_atom(PlAtom(result.c)),
                   PlTerm_float(result.d)))));
}

```

More complex structures can be built up, using `Plterm_term()`.

One other way of returning a value is to build a list of pairs, which can be used as-is or converted to a dict – the sample code for predicate `square_roots/2` (which generates the first _n_ square routes) can get you started on that:

```cpp
PREDICATE(square_roots, 2)
{ int end = A1.as_int();
  PlTerm_tail list(A2);
  for(int i=0; i<=end; i++)
    PlCheckFail(list.append(PlTerm_float(sqrt(double(i)))));
  return list.close();
}

```

---

<div class="post-metadata">

**Author:** ![maren](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/maren/32/6605_2.png) [@maren](https://swi-prolog.discourse.group/u/maren)\
**Post date:** [July 21, 2024, 3:59pm UTC](https://swi-prolog.discourse.group/t/swi-prolog-bindings-to-sdl/7610/10 "2024-07-21T15:59:00Z")

</div>

> [@peter.ludemann](#):
>
> If you do care about the contents, a dict would probably be a good way of handling a large structure; however, the only public function for dicts is `PL_get_dict_key()` (which is also available in `SWI-cpp2.h` as `Plx_get_dict_key()`. Perhaps this is an oversight, @jan?

There are more functions.  
`PL_put_dict` can create a dict. `PL_is_dict` can tell you that something is a dict.

Edit: for vanity’s sake, this is how the rust bindings wrap dictionaries: [swipl::dict - Rust](https://terminusdb-labs.github.io/swipl-rs/swipl/dict/index.html) and [Term in swipl::term - Rust](https://terminusdb-labs.github.io/swipl-rs/swipl/term/struct.Term.html)

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [July 21, 2024, 4:17pm UTC](https://swi-prolog.discourse.group/t/swi-prolog-bindings-to-sdl/7610/11 "2024-07-21T16:17:27Z")

</div>

Oops – I missed `PL_put_dict()`. There’s also `PL_for_dict()` (undocumented), for looping over keys.  
I should probably create a C++ class for dicts; but for now, the `Plx_*()` wrappers will help a bit.

---

<div class="post-metadata">

**Author:** ![kwon-young](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/kwon-young/32/4841_2.png) [@kwon-young](https://swi-prolog.discourse.group/u/kwon-young)\
**Post date:** [July 21, 2024, 7:02pm UTC](https://swi-prolog.discourse.group/t/swi-prolog-bindings-to-sdl/7610/12 "2024-07-21T19:02:02Z")

</div>

@peter.ludemann Thank you a lot for all your help and examples.

Is there a reason why the `PlTermv` function can only take 5 arguments ?  
I needed to make compounds with 8/9 arguments which mean I had to do an ugly argument by argument initialisation…

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [July 21, 2024, 7:19pm UTC](https://swi-prolog.discourse.group/t/swi-prolog-bindings-to-sdl/7610/13 "2024-07-21T19:19:51Z")

</div>

> [@kwon-young](#):
>
> Is there a reason why the `PlTermv` function can only take 5 arguments ?

There’s no reason for the limit, just a small matter of copy&paste&typing. 🙂  
[There might be some limitations with the underlying `PL_new_term_refs()`, but it’s certainly safe up to 10.]  
I can quickly make a PR for that (but it’ll take a bit of time to get into the release).  
There should be a more generic mechanism for `PlTermv`, but that’ll require more thought and possibly consultation with @jan.

Do you build your own version of `swipl`? If so, I can provide a patch.

---

<div class="post-metadata">

**Author:** ![Boris](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/boris/32/7486_2.png) [@Boris](https://swi-prolog.discourse.group/u/Boris)\
**Post date:** [July 21, 2024, 7:22pm UTC](https://swi-prolog.discourse.group/t/swi-prolog-bindings-to-sdl/7610/14 "2024-07-21T19:22:53Z")

</div>

The C interface has the variadic function [PL\_unify\_term()](https://www.swi-prolog.org/pldoc/doc_for?object=c(%27PL_unify_term%27)). Is such a design at all an option for C++?

---

<div class="post-metadata">

**Author:** ![kwon-young](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/kwon-young/32/4841_2.png) [@kwon-young](https://swi-prolog.discourse.group/u/kwon-young)\
**Post date:** [July 21, 2024, 7:23pm UTC](https://swi-prolog.discourse.group/t/swi-prolog-bindings-to-sdl/7610/15 "2024-07-21T19:23:20Z")

</div>

> [@peter.ludemann](#):
>
> Do you build your own version of `swipl`? If so, I can provide a patch.

Well, there’s nothing pressing here 🙂 If you make a PR to build compound term up to 10 terms, I’ll be happy use that when that hits fedora 40.

---

<div class="post-metadata">

**Author:** ![kwon-young](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/kwon-young/32/4841_2.png) [@kwon-young](https://swi-prolog.discourse.group/u/kwon-young)\
**Post date:** [July 21, 2024, 8:02pm UTC](https://swi-prolog.discourse.group/t/swi-prolog-bindings-to-sdl/7610/16 "2024-07-21T20:02:14Z")

</div>

> [@Boris](#):
>
> The C interface has the variadic function [PL\_unify\_term()](https://www.swi-prolog.org/pldoc/doc_for?object=c(%27PL_unify_term%27)). Is such a design at all an option for C++?

I’ve use that in my C interface and it was quite nice indeed.

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [July 21, 2024, 8:34pm UTC](https://swi-prolog.discourse.group/t/swi-prolog-bindings-to-sdl/7610/17 "2024-07-21T20:34:50Z")

</div>

> [@Boris](#):
>
> The C interface has the variadic function [PL\_unify\_term()](https://www.swi-prolog.org/pldoc/doc_for?object=c(%27PL_unify_term%27)). Is such a design at all an option for C++?

C++ is a superset of C, so a variadic form of `PlTermv` is possible. I’d have to study the code a bit to decide whether it can more-or-less copy `PL_unify_term()` (actually: `PL_unify_termv()` in `pl-fli.c`, which is nearly 250 lines of code) or requires additional work.

But a better alternative might be to use `std::vector` (and using `{...}` in the call), which would imply changing `PlCompound` and `PlTermv`. (Some additional magic can be done using overloaded constructors, to avoid the need for `PL_ATOM`, `PL_INTEGER`, etc.)

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [July 22, 2024, 7:37am UTC](https://swi-prolog.discourse.group/t/swi-prolog-bindings-to-sdl/7610/18 "2024-07-22T07:37:59Z")

</div>

> [@maren](#):
>
> Maybe some order can be forced here, where one type is always freed before the other, but that’s asking for trouble

What you can do if blob A must be freed before blob B is to add the handle for blob A to the struct of blob B and use PL\_register\_atom(B) to let the system know. Now A will be freed first, which should call PL\_unregister\_atom(B). That should make B candidate for collection in a **next** run of the garbage collector.

The alternative is to set flags in the unregister() callbacks if you cannot free immediately. So, in the above, if A is not freed and we can an unregister for B, we just mark this in B. Now if A is freed we also check whether B is flagged and then free it.
