• Places
    • Home
    • Graphs
    • Prefixes
  • Admin
    • Users
    • Settings
    • Plugins
    • Statistics
  • Repository
    • Load local file
    • Load from HTTP
    • Load from library
    • Remove triples
    • Clear repository
  • Query
    • YASGUI SPARQL Editor
    • Simple Form
    • SWISH Prolog shell
    • DSS Queries
  • Help
    • Documentation
    • Tutorial
    • Roadmap
    • HTTP Services
  • Login

11.4 The Foreign Include File
AllApplicationManualNameSummaryHelp

  • 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
          • BLOBS: Using atoms to store arbitrary binary data
            • Defining a BLOB type
            • Accessing blobs
          • Exchanging GMP numbers
          • Calling Prolog from C
          • Discarding Data
          • 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
    • Packages

11.4.7 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.

11.4.7.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 in SWI-Prolog.h. This prototype is available if the undocumented SWI-Stream.h is included before SWI-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 returns TRUE if no blobs of this type existed and FALSE otherwise. PL_unregister_blob_type() is intended for the uninstall() hook of foreign modules, avoiding further references to the module.

11.4.7.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 is TRUE 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 return FALSE. Each result pointer may be NULL, 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 11.4.7.1.

ClioPatria (version V3.1.1-21-gb8003bb)