- Documentation
- Reference manual
- Foreign Language Interface
- The Foreign Include File
- Argument Passing and Control
- Atoms and functors
- Analysing Terms via the Foreign Interface
- Constructing Terms
- Unifying data
- Convenient functions to generate Prolog exceptions
- Serializing and deserializing Prolog terms
- BLOBS: Using atoms to store arbitrary binary data
- Exchanging GMP numbers
- Calling Prolog from C
- Discarding Data
- String buffering
- Foreign Code and Modules
- Prolog exceptions in foreign code
- Catching Signals (Software Interrupts)
- Miscellaneous
- Errors and warnings
- Environment Control from Foreign Code
- Querying Prolog
- Registering Foreign Predicates
- Foreign Code Hooks
- Storing foreign data
- Embedding SWI-Prolog in other applications
- The Foreign Include File
- Foreign Language Interface
- Packages
- Reference manual
12.4.8 BLOBS: Using atoms to store arbitrary binary data
SWI-Prolog atoms as well as strings can represent arbitrary binary data of arbitrary length. This facility is attractive for storing foreign data such as images in an atom. An atom is a unique handle to this data and the atom garbage collector is able to destroy atoms that are no longer referenced by the Prolog engine. This property of atoms makes them attractive as a handle to foreign resources, such as Java atoms, Microsoft's COM objects, etc., providing safe combined garbage collection.
To exploit these features safely and in an organised manner, the SWI-Prolog foreign interface allows for creating‘atoms' with additional type information. The type is represented by a structure holding C function pointers that tell Prolog how to handle releasing the atom, writing it, sorting it, etc. Two atoms created with different types can represent the same sequence of bytes. Atoms are first ordered on the rank number of the type and then on the result of the compare() function. Rank numbers are assigned when the type is registered.
12.4.8.1 Defining a BLOB type
The type PL_blob_t
represents a structure with the
layout displayed below. The structure contains additional fields at the
... for internal bookkeeping as well as future extensions.
typedef struct PL_blob_t { uintptr_t magic; /* PL_BLOB_MAGIC */ uintptr_t flags; /* Bitwise or of PL_BLOB_* */ char * name; /* name of the type */ int (*release)(atom_t a); int (*compare)(atom_t a, atom_t b); int (*write)(IOSTREAM *s, atom_t a, int flags); void (*acquire)(atom_t a); ... } PL_blob_t;
For each type, exactly one such structure should be allocated. Its
first field must be initialised to PL_BLOB_MAGIC
. The
flags is a bitwise or of the following constants:
- PL_BLOB_TEXT
- If specified the blob is assumed to contain text and is considered a normal Prolog atom.
- PL_BLOB_UNIQUE
- If specified the system ensures that the blob-handle is a unique reference for a blob with the given type, length and content. If this flag is not specified, each lookup creates a new blob.
- PL_BLOB_NOCOPY
- By default the content of the blob is copied. Using this flag the blob
references the external data directly. The user must ensure the provided
pointer is valid as long as the atom lives. If
PL_BLOB_UNIQUE
is also specified, uniqueness is determined by comparing the pointer rather than the data pointed at.
The name field represents the type name as available to
Prolog. See also current_blob/2.
The other fields are function pointers that must be initialised to
proper functions or NULL
to get the default behaviour of
built-in atoms. Below are the defined member functions:
- void acquire(atom_t a)
- Called if a new blob of this type is created through PL_put_blob() or PL_unify_blob(). This callback may be used together with the release hook to deal with reference-counted external objects.
- int release(atom_t a)
- The blob (atom) a is about to be released. This function can
retrieve the data of the blob using PL_blob_data().
If it returns
FALSE
the atom garbage collector will not reclaim the atom. - int compare(atom_t a, atom_t b)
- Compare the blobs a and b, both of which are of the type associated to this blob type. Return values are, as memcmp(), < 0 if a is less than b, = 0 if both are equal, and > 0 otherwise.
- int write(IOSTREAM *s, atom_t a, int flags)
- Write the content of the blob a to the stream s
respecting the flags. The flags are a bitwise
or of zero or more of the
PL_WRT_*
flags defined inSWI-Prolog.h
. This prototype is available if the undocumentedSWI-Stream.h
is included beforeSWI-Prolog.h
.If this function is not provided, write/1 emits the content of the blob for blobs of type
PL_BLOB_TEXT
or a string of the format<#
hex data>
for binary blobs.
If a blob type is registered from a loadable object (shared object or DLL) the blob type must be deregistered before the object may be released.
- int PL_unregister_blob_type(PL_blob_t *type)
- Unlink the blob type from the registered type and transform the type of
possible living blobs to
unregistered
, avoiding further reference to the type structure, functions referred by it, as well as the data. This function returnsTRUE
if no blobs of this type existed andFALSE
otherwise. PL_unregister_blob_type() is intended for the uninstall() hook of foreign modules, avoiding further references to the module.
12.4.8.2 Accessing blobs
The blob access functions are similar to the atom accessing functions. Blobs being atoms, the atom functions operate on blobs and vice versa. For clarity and possible future compatibility issues, however, it is not advised to rely on this.
- int PL_is_blob(term_t t, PL_blob_t **type)
- Succeeds if t refers to a blob, in which case type is filled with the type of the blob.
- int PL_unify_blob(term_t t, void *blob, size_t len, PL_blob_t *type)
- Unify t to a new blob constructed from the given data and associated to the given type. See also PL_unify_atom_nchars().
- int PL_put_blob(term_t t, void *blob, size_t len, PL_blob_t *type)
- Store the described blob in t. The return value indicates
whether a new blob was allocated (
FALSE
) or the blob is a reference to an existing blob (TRUE
). Reporting new/existing can be used to deal with external objects having their own reference counts. If the return isTRUE
this reference count must be incremented, and it must be decremented on blob destruction callback. See also PL_put_atom_nchars(). - int PL_get_blob(term_t t, void **blob, size_t *len, PL_blob_t **type)
- If t holds a blob or atom, get the data and type and return
TRUE
. Otherwise returnFALSE
. Each result pointer may beNULL
, in which case the requested information is ignored. - void * PL_blob_data(atom_t a, size_t *len, PL_blob_t **type)
- Get the data and type associated to a blob. This function is mainly used from the callback functions described in section 12.4.8.1.