Skip to content

Rust bindings for QDMI (qdmi-rs) #351

Description

@hiq-lab

Motivation

QDMI currently provides a C API and a C tutorial for device implementations. As Rust adoption grows in the quantum computing ecosystem, official Rust bindings would lower the barrier for Rust-based quantum frameworks to integrate with QDMI.

We maintain Arvak, a Rust-native quantum compilation and orchestration platform. To use QDMI, we had to write our own FFI bindings — both for the client side (querying devices, submitting jobs) and the device side (implementing a QDMI device in Rust). These bindings are hand-written against the v1.2.1 headers and have been in production use.

What we'd contribute

A qdmi-rs crate (or qdmi-sys + qdmi split) providing:

1. Low-level FFI (qdmi-sys)

Direct mapping of all QDMI C types and functions:

  • Status codes (QDMI_STATUSQdmiStatus enum with is_success())
  • Opaque handles (QDMI_Device, QDMI_Site, QDMI_Operation, QDMI_Job)
  • All property enums (QDMI_DEVICE_PROPERTY_T, QDMI_SITE_PROPERTY_T, QDMI_OPERATION_PROPERTY_T)
  • Session parameter enums (QDMI_SESSION_PARAMETER_T, QDMI_DEVICE_SESSION_PARAMETER_T)
  • Job parameter/result enums (QDMI_DEVICE_JOB_PARAMETER_T, QDMI_DEVICE_JOB_RESULT_T)
  • All query function signatures (qdmi_session_query_*, qdmi_device_query_*, etc.)

2. Safe Rust wrappers (qdmi)

Ergonomic Rust API over the raw FFI:

  • Client side: QdmiSession, QdmiDevice, QdmiJob with RAII (Drop-based cleanup)
  • Device side: Trait-based device implementation — implement QdmiDeviceImpl trait instead of exporting C function pointers manually
  • Buffer-query pattern abstracted away (the two-call NULL → allocate → query pattern is handled internally)
  • Proper Result<T, QdmiError> error handling instead of raw status code checking

3. Device implementation via Rust traits

Instead of manually exporting prefixed C symbols, a device author would:

use qdmi::device::{DeviceImpl, DeviceInfo, SiteInfo};

struct MyQuantumDevice { /* ... */ }

impl DeviceImpl for MyQuantumDevice {
    fn name(&self) -> &str { "my-device" }
    fn num_qubits(&self) -> u32 { 20 }
    fn sites(&self) -> Vec<SiteInfo> { /* ... */ }
    fn submit(&self, program: &str, shots: u32) -> Result<JobHandle, QdmiError> { /* ... */ }
}

// Macro generates the prefixed C exports
qdmi::export_device!(MyQuantumDevice);

Current state of our bindings

Our FFI bindings cover QDMI v1.2.1 completely:

Both are Apache-2.0 licensed and could serve as the starting point.

Benefits

  • For QDMI: Broader adoption beyond C/C++ projects; Rust's safety guarantees reduce integration bugs
  • For the ecosystem: Any Rust quantum framework can use QDMI without writing private FFI
  • Maintenance: Bindings could be auto-generated from QDMI headers via bindgen, staying in sync with releases

Happy to discuss scope and submit a PR. We could start with just qdmi-sys (raw FFI) and iterate on the safe wrapper API based on feedback.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions