We've run into a situation fairly regularly when wrapping C libraries where we'd like to avoid making extra copies of data when passing it between Dylan and C code via the C-FFI. Related to this, we want to be able to use multiple types from the Dylan side of things such as <buffer>, <byte-vector> or <byte-string> without having to have separate code paths for each of them. Each of these classes can store raw byte data that we may want to share with other code.
An example that we'll work with in this discussion comes from bindings (in simplified and excerpted forms) for the LevelDB library:
extern void leveldb_put(
leveldb_t* db,
const leveldb_writeoptions_t* options,
const char* key, size_t keylen,
const char* val, size_t vallen,
char** errptr);
<C-string>
The easiest way to bind leveldb_put would be to use <C-string>:
define C-function %leveldb-put
input parameter db_ :: <leveldb-t*>;
input parameter options_ :: <leveldb-writeoptions-t*>;
input parameter key_ :: <C-string>;
input parameter keylen_ :: <size-t>;
input parameter val_ :: <C-string>;
input parameter vallen_ :: <size-t>;
output parameter errptr_ :: <char**>;
c-name: "leveldb_put";
end;
However, this would mean that every key and value would have to be copied from an existing byte container (like <buffer>, <string> or <byte-vector>) to ...
There are comments.