Probably “blobs” are a better interface than raw pointers; but they require a bit more work. I’m planning on a C++ interface to blobs, to make it easier to use them.
As for PL_register_foreign() et al, the 2nd argument is the arity: this determines the number of term_t arguments you need to put in your function. E.g., the “regex” foreign library has:
PL_register_foreign("re_compile, 3, re_match_, 0);
which corresponds to
static foreign_t
re_compile_(term_t pat, term_t reb, term_t options)
{ ...
}
(If you used the C++ interface, then you’d write PREDICATE(re_compile 3) and reference pat using A1, reb using A2, and options using A3.)