In this section, the blob is of type MyBlob
, a subclass
of PlBlob
.
A blob is typically created by calling a predicate that does the following:
auto ref = std::unique_ptr<PlBlob>(new
MyBlob>(...))
(std::make_unique() can't be used because it
returns type
std::unique_ptr<MyBlob>
but
PlTerm::unify_blob() requires a
std::unique_ptr<PlBlob>
and C++'s type
inferencing can't figure out that this is a covariant type).
ref.release()
to pass ownership to the Prolog blob. If you
wish to use std::make_unique<MyBlob>(), you could
instead do:
auto ref = std::make_unique<MyBlob>(...); ... // code that accesses fields in *ref std::unique_ptr<PlBlob> refb(ref.release()); // transfer ownership of ptr // from here on, can't access fields in *ref return A2.unify_blob(refb);
At this point, the blob is owned by Prolog and will be freed by its atom garbage collector, which will call the blob's destructor.
Whenever a predicate is called with the blob as an argument (e.g., as A1),
the blob can be accessed by
PlBlobv<MyBlob>::cast_check(A1.as_atom())
.
Within a method, the Prolog blob can be accessed as a term (e.g., for
constructing an error term) using the method MyBlob::symbol_term(). This
field is initialized by the call to PlTerm::unify_blob(); if
MyBlob::symbol_term() is called before a successful call to
PlTerm::unify_blob(), MyBlob::symbol_term() returns a
PlTerm_var
.
When the atom garbage collector runs, it frees the blob by first
calling the release() callback, which does delete
, which
calls the destructor MyBlob:: MyBlob(). Note that C++ destructors
are not supposed to raise exception; they also should not cause a Prolog
error, which could cause deadlock unless the real work is done in
another thread.
Often it is desired to release the resources before the garbage collector runs. To do this, the programmer can provide a "close" predicate which is the inverse of the "open" predicate that created the blob. This typically has the same logic as the destructor, except that it can raise a Prolog error.