Registering a foreign predicate


How do you register a foreign predicate with SWI-Prolog, when the main-
function is written in Prolog, not C?


Prolog-side code:

load_foreign_extensions :- % if it's already loaded, don't load again.
    current_predicate(vector_create/1), !. 

load_foreign_extensions :-                      % shared library
   -> writeln('nb_vector is loaded')
    ; writeln(failed(load_foreign_extensions)).

C side code, compiled into nb_vector.dll:

static foreign_t create_vector(term_t term)
  std::vector<char> *x = new std::vector<char>();
  PL_unify_blob(term, x, sizeof(*x), &vector_blob);

extern "C" install_t    install()
  PL_register_foreign("vector_create", 1, create_vector, 0);

?- load_foreign_extensions.
?- vector_create(V).
V = …

1 Like

Thanks for the answer.

I think I’ll rather make a small main() function on the C side, so I can link it statically.


P.S. create_vector is a memory leak. Obviously I also have a delete_vector and useful methods beyond that.

As is, the vector data is in the blob. The blob declaration itself misses. They can be defined to copy the data or to use the supplied memory area (default: copy). If the data is copied, the original may be destroyed immediately. If the data is not copied, the free hook shall be defined to release the memory.

Note that that presented handling of vectors as blobs is dubious. I suppose the idea is to modify the vector. That violates the assumption that the content of an atom should be immutable. Typically you put the pointer in the blob.

On the ROS interface I’m working on I’ve created a small abstraction over blobs. See rclswi/pointer.c at 8feb27ee1c326b02d8520c72ca3e050b6d572c9d · SWI-Prolog/rclswi · GitHub I’m not completely happy with it. Possibly the abstraction that is used in the ffi package is better. That notably allows defining that the data of one blobs depends on others.

I believe, Jan, it is not the vector in the blob, but a pointer to the vector. Which itself points to a different memory area which is its content (initially empty). The code is working quite reliably so that gives me confidence your interpretation may be off. But if you are sure, we can discuss further.

It is definitely the vector itself. Well, not the actual data as that is in some area referenced by the vector class. Whether or not this is bad depends on how you declare the blob and whether or not you create multiple blobs from the same C++ object. You probably want to use PL_BLOB_NOCOPY to avoid Prolog becoming the owner of the data.