Skip to content

Commit cb3b328

Browse files
committed
docs: Add docs for FFI ownership
1 parent 1e2f7ba commit cb3b328

2 files changed

Lines changed: 30 additions & 1 deletion

File tree

rust/lib.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@ mod error;
1616
use scanner::LanceStream;
1717
use error::{clear_last_error, set_last_error, ErrorCode};
1818

19+
// FFI ownership contract (Arrow C Data Interface):
20+
// - All `*_open/create/get` functions return opaque handles owned by the caller,
21+
// which must be released exactly once via the matching `*_close/free` call.
22+
// - `lance_schema_to_arrow` transfers ownership of the populated ArrowSchema to
23+
// the caller. The caller must call `release` exactly once on success.
24+
// - `lance_batch_to_arrow` transfers ownership of the populated ArrowArray and
25+
// ArrowSchema to the caller. The caller must call `release` exactly once on
26+
// each on success.
27+
// - On error (non-zero return), output ArrowSchema/ArrowArray are left
28+
// untouched and must not be released unless the caller initialized them to a
29+
// valid value before calling into this library.
30+
1931
// Dataset operations - just holds the dataset
2032
struct DatasetHandle {
2133
dataset: Arc<Dataset>,
@@ -246,7 +258,6 @@ pub unsafe extern "C" fn lance_create_fragment_stream(
246258
}
247259
}
248260
}
249-
250261
scan.scan_in_order(false);
251262

252263
match LanceStream::from_scanner(scan) {

src/lance_scan.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,21 @@
2525
#include <cstdint>
2626
#include <cstring>
2727

28+
// FFI ownership contract (Arrow C Data Interface):
29+
// - `lance_get_schema` returns an opaque schema handle. The caller must release
30+
// it exactly once via `lance_free_schema`.
31+
// - `lance_schema_to_arrow` populates `out_schema` on success (return 0) and
32+
// transfers ownership of the ArrowSchema to the caller, who must call
33+
// `out_schema->release(out_schema)` exactly once (or wrap it in RAII).
34+
// - `lance_create_stream`/`lance_create_fragment_stream` return an opaque stream
35+
// handle. The caller must release it exactly once via `lance_close_stream`.
36+
// - `lance_stream_next` returns an opaque RecordBatch handle. The caller must
37+
// release it exactly once via `lance_free_batch` after use.
38+
// - `lance_batch_to_arrow` populates `out_array` and `out_schema` on success
39+
// (return 0) and transfers ownership of both to the caller, who must call
40+
// `release` exactly once on each.
41+
// - On error, the callee leaves output `ArrowSchema`/`ArrowArray` untouched; do
42+
// not call `release` unless the caller initialized them to a valid value.
2843
extern "C" {
2944
void *lance_open_dataset(const char *path);
3045
void lance_close_dataset(void *dataset);
@@ -524,6 +539,8 @@ static unique_ptr<FunctionData> LanceScanBind(ClientContext &context,
524539
result->file_path + LanceFormatErrorSuffix());
525540
}
526541

542+
memset(&result->schema_root.arrow_schema, 0,
543+
sizeof(result->schema_root.arrow_schema));
527544
if (lance_schema_to_arrow(schema_handle, &result->schema_root.arrow_schema) !=
528545
0) {
529546
lance_free_schema(schema_handle);
@@ -676,6 +693,7 @@ static bool LanceScanLoadNextBatch(LanceScanLocalState &local_state) {
676693
}
677694

678695
auto new_chunk = make_shared_ptr<ArrowArrayWrapper>();
696+
memset(&new_chunk->arrow_array, 0, sizeof(new_chunk->arrow_array));
679697
ArrowSchema tmp_schema;
680698
memset(&tmp_schema, 0, sizeof(tmp_schema));
681699

0 commit comments

Comments
 (0)