Qiskit beyond Python: Fortran, C++, and Julia

Источник: IBM

Qiskit beyond Python: Fortran, C++, and Julia

Source: IBM

Qiskit’s C API connects the SDK’s Rust core to the languages of HPC and scientific computing, so you can build and run circuits natively—no Python required.

•Updated: October 6, 2026

Key takeaways:

  • Qiskit's C API lets you work with Qiskit natively from Fortran, C++, and Julia—no Python required—by exposing the SDK's high-performance Rust core.
  • Since Qiskit v2.0, a single C interface connects the SDK's Rust core to nearly every programming language used in HPC and scientific computing.
  • Because all language bindings share the same Qiskit library, they interoperate: build a circuit in Fortran and pass it to C++.
  • Native bindings make integrating Qiskit into hybrid quantum-classical HPC workflows straightforward, advancing quantum computing for optimization, machine learning, and scientific simulation.

Qiskit is the world’s most popular software development kit for quantum computing, and most people meet it through the Python programming language. But Python isn’t the only entry point.

Since Qiskit v2.0, the SDK has exposed a C API to its core data model—the same high-performance Rust core that powers the Python SDK. Because C interoperates with nearly every programming language, that single interface opens a door to many others. Three of them—Fortran, C++, and Julia—now let you work with quantum circuits in the same language you use for everything else. The result is quantum computing you can fold directly into your existing code, no Python layer required.

Crucially, because every language binding is backed by the same Qiskit shared library, they’re interoperable as well. In principle, you could build a circuit in Fortran and pass it to C++. It should run without issue because both language bindings point to the same object.

These interfaces are important because we believe quantum computing will be a revolutionary paradigm for scientific computing. As we’ve seen with recent demonstrations from IBM and its partners, quantum computing delivers its advantage in combination with classical resources, not apart from them.

Researchers have spent years exploring quantum methods for optimization, machine learning, and simulations of complex quantum systems and dynamics. Much of that work occurs in languages other than Python.

Even when Python does drive the workflow, the compute-heavy cores of many simulation codes in physics, chemistry, and engineering are typically written in Fortran and C++, and increasingly in Julia. And in many HPC communities, these languages carry the science itself, with shell or Python scripts doing little more than orchestrating the pieces.

Experimenting with quantum computing shouldn’t force classical applications researchers to bolt a Python interpreter onto their existing code. To help the research community fully explore the potential of quantum computing, we have to ensure that integrating Qiskit into hybrid quantum-classical workflows is straightforward—regardless of the language you use.

Ready to see what native Qiskit code can do for your research? Create a free account on IBM Quantum Platform to run experiments on real quantum hardware, and explore the documentation to bring Qiskit into your Fortran, C++, and Julia workflows.

Three paths into Qiskit: Fortran, C++, and Julia

The three paths into Qiskit may be different, but they share a common foundation: each binds to the C API and talks directly to Qiskit’s Rust core. Perhaps more importantly, each aims to meet the research community on its own terms. Here’s what that looks like in practice:

Fortran

Fortran is among the oldest high-level programming languages. It was originally introduced as a “formula translating system,” enabling scientists to write numerical expressions directly and have them compiled to fast machine code.

Decades later, it still underpins large swaths of HPC and scientific computing communities. Core linear-algebra libraries such as BLAS and LAPACK are implemented in Fortran, as are workhorse quantum-chemistry codes like Gaussian, VASP, Quantum ESPRESSO, CP2K, GAMESS, NWChem, and nuclear-physics tools like KSHELL, BIGSTICK, and MFDn.

To bring quantum computing closer to these application domains, we’ve built qiskit-fortran, a Fortran interface for building and manipulating quantum circuits. Its design was shaped through active discussion with the Fortran developer community, helping ensure the interface fits naturally into existing Fortran workflows.

Under the hood, it binds to the Qiskit C API through Fortran’s standard foreign-function interface (iso_c_binding), calling the C API functions directly so you don’t have to write the bindings yourself. Those calls reach the same Rust core that powers the Python SDK, without going through Python at any point.

In qiskit-fortran, a QuantumCircuit is a derived type with a FINAL destructor, meaning the circuit releases its memory when the variable goes out of scope. You can focus on the physics: an FCIDUMP active-space Hamiltonian from GAMESS, already resident in Fortran memory, passes to a Qiskit circuit-construction routine as a direct pointer—no copy into Python objects, no GIL, no reallocation.

By keeping the workflow native, we eliminate the need for an intermediate Python layer, creating opportunities for tighter, more performant integration with existing Fortran applications.

Find a detailed example workflow in our qiskit-fortran tutorial.

C++

The C++ programming language began as an extension of C with classes, adding high-level abstraction without runtime overhead. This makes it the workhorse of performance-critical simulation, from molecular dynamics software like LAMMPS and GROMACS to accelerator layers like CUDA and Kokkos that program today’s exascale machines.

First announced last year, qiskit-cpp is a header-only C++ interface to Qiskit’s C API. Add its headers to your include path, link your program against Qiskit’s C library, and compile once from the Qiskit source tree.

Here, a QuantumCircuit is a C++ object with syntax close to the one we use in Python, and it frees its own memory when it goes out of scope. Execution is flexible: circuits can be submitted through the qiskit-ibm-runtime C client, through QRMI or through SQC.

Find an example workflow in the qiskit-cpp tutorial.

Julia

Julia is a programming language designed to combine the speed of a compiled language with the ease of a dynamic one. In many ways, it offers the gentlest on-ramp to using Qiskit outside of Python. There’s no need to build from source, and it runs in Jupyter notebooks, so you can work interactively just as you would in Python.

Qiskit.jl wraps the Qiskit C API and exposes it as native Julia types, so you don’t need to worry about managing C pointers yourself. Circuit construction is similar to the syntax in Python, but the package also offers an idiomatic Julia style if you prefer it. The same binding strategy extends to circuit execution: QiskitIBMRuntime.jl, a lightweight wrapper for the qiskit-ibm-runtime C client, submits circuits to IBM Quantum hardware and retrieves results.

With these two packages, you can now run a complete quantum workflow in Julia—and connect it to the rest of the Julia ecosystem. That ecosystem offers a variety of useful tools for scientific computing, including differential equation solvers like DifferentialEquations.jl and optimization libraries like Optimization.jl.

The Julia ecosystem also offers many tools that are relevant for quantum computing, including tensor network simulation tools like ITensors.jl and TensorNetworkQuantumSimulator.jl—valuable resources you can use to validate quantum results against approximate classical simulations.

Get started: simulating quantum dynamics on 100 qubits

To give you a better sense of what it’s like to work with Qiskit outside of Python, let’s dig a bit deeper into Qiskit.jl with a brief tutorial. We’ll walk through the process of circuit construction and hardware execution using a quantum approach to the Schrödinger equation, which describes how a quantum system evolves in time under its Hamiltonian—a mathematical object that describes the system and generates its time evolution.

Quantum computers are naturally suited to solving the Schrödinger equation; they can simply evolve the quantum state encoded in their qubits. Because that evolution must be carried out with discrete quantum gates, we approximate it through a process called Trotterization, where we break the dynamics into small steps. Smaller steps give us lower discretization error, but deeper circuits to run.

The test system is the transverse-field Ising model—a 1D chain of spins with nearest-neighbor coupling, evolved from an initial Néel state |0101…⟩. From there, the workflow follows the same four steps as most quantum workflows: (1) map the problem to a circuit, (2) optimize that circuit for hardware, (3) execute on hardware, and (4) post-process results.

The only difference is that here, every step runs in Julia.

Step 1: Map the problem to circuits. Each Trotter step becomes a layer of single-qubit Rx rotations and two-qubit Rzz gates. In Qiskit.jl, a circuit is a native Julia object, and the construction API uses idiomatic Julia, mutating functions with a ! suffix that take the circuit as their first argument, while still corresponding to the Python SDK almost line for line:

using Qiskit using Qiskit.Operations function make_trotter_circuit(h, J, n, δt, steps) qc = QuantumCircuit(n, n) for i in 1:2:n x!(qc, i) end # prepare the Néel state |0101…⟩ for _ in 1:steps # one second-order Trotter step for i in 1:n rx!(qc, h[i] * δt, i) end for i in 1:n-1 rzz!(qc, 2J[i] * δt, i, i+1) end for i in 1:n rx!(qc, h[i] * δt, i) end end for i in 1:n measure!(qc, i, i) end return qc end

If you've built circuits with Qiskit in Python, rx!(qc, θ, i) and rzz!(qc, θ, i, j) map directly onto qc.rx(θ, i) and qc.rzz(θ, i, j). The one thing to watch out for is indexing: Julia counts qubits from 1, as is standard in Julia, whereas Python counts from 0.

Step 2: Optimize for hardware. Before a circuit can run, it must be transpiled to a specific backend—mapped onto physical qubits, rewritten in the device's native gates, and optimized for depth. Qiskit.jl exposes the same transpiler:

using QiskitIBMRuntime service = Service() backend = least_busy(backend_search(service)) target = target_from_backend(backend, service) tqc = transpile(qc, target)[1] # map onto physical qubits and optimize depth

Step 3: Execute. QiskitIBMRuntime.jl submits the transpiled circuit to the backend as a Sampler job and retrieves the results—no leaving Julia to reach the hardware:

job = run_sampler_job(service, backend, tqc, shots) samples = get_job_results(job, service) # blocks until the job completes

Step 4: Post-process. Finally, we turn the measured bitstrings back into physics—here, the site magnetization ⟨Zi⟩ averaged over shots—with ordinary Julia code, in the same session:

using Statistics z_expval(samples, i) = mean((-1)^s[i] for s in samples)

At a small scale, let’s say 20 qubits, you can check the hardware results against a classical reference. The OrdinaryDiffEq.jl ODE solver provides an exact solution, while a noiseless tensor-network simulation offers a second check. The quantum results track both closely.

At 100 qubits, the exact solution is out of reach—the state vector alone would need 2 ≈ 10 amplitudes, so a noiseless tensor-network simulation becomes the reference. This reference is trustworthy only when the state remains weakly entangled, typically at early evolution times. As the dynamics build more entanglement than the tensor network can faithfully represent, its error compounds quickly and the simulation can no longer serve as a reliable reference.

This is where the quantum approach shows its value. Classically, each additional spin doubles the size of the state vector needed to represent the system. On the quantum hardware, each additional spin maps to one additional qubit, so a 100-spin system maps onto 100 qubits. Additionally, the hardware carries the entanglement instead of truncating it to fit an ansatz. That shifts the accuracy question away from how much correlation a classical representation can afford, and onto Trotter error and hardware noise.

The 100-qubit run demonstrates this tradeoff: reducing the Trotter step lowers the discretization error but deepens the circuit, and once the step is small enough that the added depth introduces more noise than the finer step removes in Trotter error, further reductions no longer improve accuracy. The step size must be chosen to balance the two.

Solving dynamical equations at high accuracy is believed to be one of the problems where quantum computers will eventually outperform classical ones. This tutorial is a great place to start experimenting today, with Julia as your interface.

Be sure to check out the full tutorial, which walks through every step as an executable Julia notebook.

Why this matters for quantum-centric supercomputing

The tight coupling between classical code and quantum instructions that we see in the example above is exactly what makes the Qiskit C API compelling for quantum-centric supercomputing (QCSC)—an emerging framework that has enabled the first demonstrations of quantum advantage. A quantum call becomes a linked subroutine inside an existing simulation code, rather than a separate process or Python sub-interpreter to orchestrate.

All three paths outlined in this blog post share this property. Fortran, C++, and Julia each reach Qiskit’s Rust core through a direct native call, with no interpreter in between. That means you can write your own piece of the workflow—a custom Trotter decomposition, a novel ansatz, a problem-specific error-mitigation estimator, or a cost function the optimizer evaluates on quantum hardware thousands of times—in the language the rest of your code already speaks.

Build with us

If you’re a researcher working on applications that might benefit from quantum computing in Fortran, C++, or Julia, we hope you’ll take some time to explore whichever tutorial fits your domain. Try it and execute your quantum workflow on real hardware. Then take it a step further and ask what problem you’d most like to solve on a quantum computer.

All of these non-Python bindings are in active development. If you have feedback or would like to contribute, please open an issue or a pull request. We’re building these paths for your community, and we hope you’ll join us in the effort.

Bring quantum computing into your codebase today. Visit IBM Quantum Platform to create a free account, run experiments on real quantum hardware, and explore the C API documentation, tutorials, and bindings for Fortran, C++, and Julia.

What this article says

Something is unclear? Ask about the article — I will explain in plain words.

Do not want to dig deeper? We will sort it out for you.