Ropendal exposes a pure C API in
inst/include/ropendal.h for downstream native packages. The
purpose is direct OpenDAL-backed byte I/O from native code: submit async
work, wait on Aio handles, and read borrowed results or fill
caller-owned buffers without calling R while background I/O is running.
The exported C symbols are implemented in Rust and documented by the
installed header.
C calls mirror the package’s async behavior:
*_aio() for submission,ropendal_aio_wait() / monitor helpers for
completion,A downstream package uses the normal R package mechanism to get the header:
LinkingTo: Ropendal
Imports: Ropendal
Native code can then include the installed header:
If the downstream shared library calls Ropendal symbols directly, its
build system must also arrange for Ropendal’s native library to be
loaded/linked before those calls. The C interface itself remains pure C
and does not require R headers or SEXP values.
// allocate a filesystem handle
ropendal_fs_t *fs = NULL;
ropendal_error_t *err = NULL;
ropendal_kv_t cfg = {
.struct_size = sizeof(cfg),
.key = "root",
.value = "/tmp/ropendal-example"
};
ropendal_fs_open("fs", &cfg, 1, &fs, &err);
// submit async read and wait
ropendal_read_options_t opts = {
.struct_size = sizeof(opts),
.path = "object.bin"
};
ropendal_aio_t *aio = NULL;
ropendal_status_t status = ropendal_read_aio(fs, &opts, &aio, &err);
if (status == ROPENDAL_OK) {
ropendal_aio_wait(aio, -1, &err);
const uint8_t *data = NULL;
size_t len = 0;
ropendal_aio_result_bytes(aio, &data, &len, &err);
}
// always release native resources
ropendal_aio_release(aio);
ropendal_fs_release(fs);
ropendal_error_release(err);Downstream packages can perform byte-oriented async operations without going through R-level raw allocation. This keeps the native path fast and explicit while using the same transport semantics as the user-facing R API.