C ABI bridge around timsrust.
This project exposes a small stable C interface for reading Bruker .d datasets (TDF/miniTDF) through Rust, and provides a C++ example for basic usage.
- Working prototype that exposes a small C ABI for reading Bruker
.ddatasets. - The crate can be built in two modes:
- With real reader support enabled (
--features with_timsrust) — provides full functionality and real data access. - Without the feature (default) — provides lightweight stubs that allow building and exercising the C ABI surface for CI and development without the
timsrustdependency.
- With real reader support enabled (
- Example client in
examples/cpp_client.cppprints OpenMS FileInfo-like output when built against the real reader.
Note
A future timsrust release may include refactors that require updating the integration points in this crate when upgrading the dependency.
Header: include/timsrust_cpp_bridge.h
Implemented API (high level):
- Dataset lifecycle:
tims_opentims_closetims_get_last_error
- Counts and metadata:
tims_num_spectra(expanded MS2 spectra)tims_num_frames(raw LC frames)tims_get_swath_windowstims_free_swath_windows
- Spectrum access:
tims_get_spectrumtims_get_spectra_by_rttims_free_spectrum_array
- Aggregate statistics:
tims_file_info(per-level counts/ranges + total peaks + timing)
This crate supports two build modes. By default the crate builds without the external timsrust dependency and provides minimal stubs for the FFI surface. To enable real dataset reading you must enable the with_timsrust feature.
Build with real reader support (recommended for actual dataset access):
cargo build --features with_timsrust --releaseBuild only the FFI surface (no timsrust dependency; useful for CI or compilation tests):
cargo build --releaseArtifacts are generated in target/release/ (or target/debug/ if not using --release). Expected artifacts include platform-specific shared/static libraries, for example libtimsrust_cpp_bridge.so on Linux.
Include the header and link against the built library. When linking against a build that used --features with_timsrust the API will access real data; when linking against a build without the feature, the functions are present but operate as minimal stubs.
g++ -std=c++17 your_app.cpp \
-Iinclude \
-Ltarget/debug -ltimsrust_cpp_bridge \
-Wl,-rpath,$(pwd)/target/debug \
-o your_app#include <iostream>
#include "include/timsrust_cpp_bridge.h"
int main(int argc, char** argv) {
if (argc < 2) return 1;
tims_dataset* ds = nullptr;
if (tims_open(argv[1], &ds) != TIMSFFI_OK) {
char err[1024] = {0};
tims_get_last_error(nullptr, err, sizeof(err));
std::cerr << "open failed: " << err << "\n";
return 1;
}
unsigned int ms2 = tims_num_spectra(ds);
unsigned int frames = tims_num_frames(ds);
std::cout << "ms2 spectra: " << ms2 << "\n";
std::cout << "raw frames: " << frames << "\n";
tims_file_info_t info{};
if (tims_file_info(ds, &info) == TIMSFFI_OK) {
std::cout << "total peaks: " << info.total_peaks << "\n";
std::cout << "ms2 count: " << info.ms2.count << "\n";
}
tims_close(ds);
return 0;
}- For DIA-PASEF datasets,
tims_num_spectrareflects expanded MS2 spectra, whiletims_num_framesreflects raw LC frames (including MS1). tims_file_infoperforms a full scan and can take significant time on large datasets.- Error details are available via
tims_get_last_error.
Additional notes:
- The
with_timsrustfeature must be enabled to access real Bruker.ddatasets. Building without the feature will succeed but return empty/default values from reader functions — this is intentional for CI and development wheretimsrustmay not be available. - Placeholder project files included in the repository (for example
build.rs,cbindgen.toml, andsrc/errors.rs) are intentionally present to keep the build surface consistent and to support downstream tooling. We recommend tracking them in git so collaborators and CI have a reproducible workspace. - When preparing artifacts for consumption by native projects (e.g., OpenMS) consider producing a release bundle containing the shared/static library and the header file to avoid requiring consumers to use Cargo directly.
See examples/README.md for build and run instructions for examples/cpp_client.cpp.