Skip to content

[C-API] SVS Pure-C API binding - #284

Open
rfsaliev wants to merge 32 commits into
mainfrom
dev/c-api
Open

[C-API] SVS Pure-C API binding#284
rfsaliev wants to merge 32 commits into
mainfrom
dev/c-api

Conversation

@rfsaliev

Copy link
Copy Markdown
Member

NOTE: This PR is in-progress and marked as 'Draft' to prevent merging until completion

Scalable Vector Search C API bindings.

This pull request introduces a new C API binding for the project, providing C language access to the core Scalable Vector Search (SVS) functionality. The changes add a complete build system for the C API, define the public C API headers, and include a sample program to demonstrate usage. The most important changes are grouped below:

C API Design Document

  • Added the bindings/SVS_C_API_Design.md document which describes the design proposal for the Scalable Vector Search (SVS) C API including: architecture overview, core components design, naming conventions, usage rules, draft API reference, etc.

C API Implementation and Build System:

  • Added a new bindings/c directory with a CMakeLists.txt to build the shared library svs_c_api, set up installation rules, and link dependencies such as OpenMP and the core SVS library.
  • Updated the root CMakeLists.txt to include the new C API bindings in the build process.
  • Added a CMake config template (c_apiConfig.cmake.in) for downstream projects to find and use the C API library.

C API Public Headers:

  • Introduced svs_c.h and svs_c_config.h in bindings/c/include/svs/c_api/, defining the C API's types, enums, opaque handles, and functions for error handling, algorithm configuration, storage configuration, index building, searching, and result management. [1] [2]

Samples and Demonstration:

  • Added a samples directory with a CMakeLists.txt to build a simple example (c_api_simple) demonstrating how to use the new C API.

rfsaliev and others added 28 commits March 4, 2026 15:22
Add `svs_index_load()` and `svs_index_save()` API implementation for
static Vamana index
Done:

- [x] Create dynamic index with specified block size (default block size
should be supported)
- [x] Initialized with a dataset and labels list
- [x] Add labeled vectors to a dynamic index
- [x] Remove vectors by labels
- [x] Check if a label exists
- [x] Compute distance for label
- [x] Get vector by label
- [x] Consolidate/compact dynamic index
- [x] Implement Save/Load
Adds `svs_index_get_num_threads` / `svs_index_set_num_threads` to the C
API, enabling dynamic inspection and resizing of the search threadpool
after index construction.

### ThreadPoolBuilder
- Added `get_threads_num()` — delegates to the custom pool's `size()` op
when `kind == CUSTOM`, otherwise returns the stored count
- Added `resize(n)` — updates stored thread count; throws
`std::invalid_argument` for `n == 0`, `SINGLE_THREAD`, or `CUSTOM` kinds
(surfaced as `SVS_ERROR_INVALID_ARGUMENT` through `wrap_exceptions`)

### Index wrappers (`index.hpp`)
- `Index` stores a `ThreadPoolBuilder`; `get_num_threads()` is
pure-virtual — implemented in `IndexVamana` and `DynamicIndexVamana` by
delegating to the wrapped `svs::Vamana` / `svs::DynamicVamana` instance,
so the value reflects actual runtime state
- `set_num_threads(n)` calls `pool_builder.resize(n)` then rebuilds and
installs the threadpool via `set_threadpool()`

### C API (`svs_c.cpp` / `svs_c.h`)
- Both entry points validate `index->impl` non-null before dereferencing
(consistent with existing handle-check pattern)
- Public header documents supported kinds and expected error codes for
unsupported configurations
Resolve cmake version compatibility issue caused by using
DOWNLOAD_EXTRACT_TIMESTAMP which is introduced in v.3.24

This PR fixes #317
…306)

This pull request introduces a comprehensive C API test suite for the
SVS project, leveraging the Catch2 testing framework. It adds new test
files covering all major C API functionalities, integrates automated
test building and execution into the CMake build system, and improves
error handling and testability for dynamic index operations.

**C API Test Infrastructure and Test Coverage:**

* Added a new directory of C API tests using Catch2, with individual
test files for error handling, algorithm configuration, storage, search
parameters, index building, and dynamic index operations.

**Dynamic Index Error Handling:**

* Refactored `svs_index_dynamic_delete_points` to improve error handling.
- Introduced `svs_id_filter_interface`  to define filtering operations.
- Implemented `svs_index_search_topK` to support an optional ID filter
for search operations.
- Updated existing search functions to use the new filtered search
capabilities.
- Added a new source file `filtered_search.hpp` containing the logic for
filtered top-K search.
- Modified existing samples and tests to demonstrate and validate the
new filtering functionality.
- Marked the previous `svs_index_search` function as deprecated,
directing users to use `svs_index_search_topK` instead.
…n) (#354)

## Summary

Exposes memory accounting in the **C API** for the Valkey-search
integration:

- `svs_index_get_memory_usage(index, size_t* out_bytes, err)` — total
allocated bytes.
- `svs_index_get_memory_breakdown(index, svs_memory_breakdown_t* out,
err)` — `{graph_bytes, data_bytes, metadata_bytes}` component split.
~~- `svs_index_element_size(index, size_t* out_bytes, err)` — bytes per
stored vector.~~ (keep at data level)

All follow the existing C API conventions (out-param + `svs_error_h`,
`wrap_exceptions`), matching the Phase-A design in the memory-accounting
contract (intel-innersource #333).

## Layers

- **C API** (`bindings/c`): the three functions +
`svs_memory_breakdown_t` in `svs_c.h`; interface virtuals + concrete
overrides in `src/index.hpp`; impls in `src/svs_c.cpp`.
- **Core / orchestrator**: brings in `get_memory_breakdown()`
(`MemoryBreakdown` struct + capacity-based
`svs::data::detail::dataset_allocated_bytes` helper) on `VamanaIndex` /
`MutableVamanaIndex` and through the orchestrator, plus an
`element_size()` accessor parallel to `dimensions()`. This mirrors the
approved public PR #345 so the C API can build and test standalone; once
#345 lands on `dev/c-api`, this reduces to just the C API layer.

## Tests

`bindings/c/tests/c_api_index.cpp` (static) and
`c_api_dynamic_index.cpp` (dynamic): usage > 0, breakdown total ==
usage, `graph_bytes`/`data_bytes` > 0 (metadata > 0 for dynamic),
`element_size == sizeof(float) * dimensions`, and null-arg handling.
Both test cases pass (84 / 166 assertions).

Related: builds on #345; memory-accounting
contract in intel-innersource #333 / #326.
#360 reopened directly
to C API branch

---------

Co-authored-by: Rafik Saliev <rafik.f.saliev@intel.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Comment thread examples/c/CMakeLists.txt

@ethanglaser ethanglaser Aug 13, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a difference between scope of these "samples" vs. "examples" in repo root? I'd say it'd be more aligned with the rest of the repo to move bindings/c/samples to examples/c

@rfsaliev rfsaliev Aug 18, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the note.
As far as bindings/c is not referenced in the root CMakeLists.txt, I would do following steps:

  1. Add bindings/c to the root CMake configuration (controlled by option SVS_BUILD_C_API)
  2. Move binding/c/samples to examples/c
  3. Modify examples/CMakeLists to add_subdirectory("c") if SVS_BUILD_C_API is ON (or if(TARGET svs_c_api) )
  4. Modify/update CI workflow and scripts to use root CMake directory for C API building

These changes can be made in this PR, or later upon merge - @ethanglaser, your opinion?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it can be done in this PR easily enough, unless there was a reason we avoided doing this. It would align with runtime bindings and the remainder of the repo which would be preferable

@rfsaliev rfsaliev Aug 19, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would align with runtime bindings and the remainder of the repo which would be preferable

Unfortunately, there is no examples for runtime bindings and no reference to runtime bindings from the root CMakeLists.txt. It seems C API samples/examples cannot be aligned with

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've moved bindings/c/samples to examples in the last commit.

**Important note:**
> **This API refactoring breaks compatibility with existing client code**

Refactor API for better consitency, stability, extensibility.
- Updated ThreadPoolBuilder to ensure custom threadpool pointers are validated and initialized correctly.
- Enhanced error handling in parallel_for method to catch exceptions and rethrow them appropriately.
- Modified IDFilterAdapter to check for null operations and validate filter rates during initialization.
- Adjusted test cases to reflect changes in function signatures and ensure proper error handling.
- Introduced new utility functions for initializing search results and memory breakdown structures.
- Updated sequential threadpool implementation to return a boolean indicating success
- All public headers moved to `include/svs/c/`, and installation paths
updated to match, replacing the old `c_api` directory.
- Added generated version header `svs_c_version.h` with version macros, configured and installed via CMake.
- Refactored `svs_search_result_t` structure now allows user to pre-allocate result buffers.
- Added a detailed `README.md` for the C API, including build instructions, usage, and sample code.
@rfsaliev
rfsaliev marked this pull request as ready for review August 18, 2026 10:18
@rfsaliev
rfsaliev requested a review from ethanglaser August 19, 2026 15:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants