# KCL Multi-Language SDK Architecture: How Rust, Go, and Python Bindings Work

> Explore KCL's multi-language SDK architecture. Discover how Rust, Go, and Python bindings leverage a Rust core via C-API and Protocol Buffers for seamless compiler interaction.

- Repository: [The KCL Programming Language/kcl](https://github.com/kcl-lang/kcl)
- Tags: architecture
- Published: 2026-03-05

---

**KCL's multi-language SDK architecture exposes a Rust-based core through a stable C-API and Protocol Buffer definitions, enabling idiomatic Rust, Go, and Python SDKs to interact with the compiler via native linking, CGO, or CFFI respectively.**

KCL (KCL Constraint-based Record & Functional Language) is implemented in **Rust**, but its configuration language capabilities extend to **Go** and **Python** ecosystems through a unified multi-language SDK architecture. By exposing a **public C-API** together with a **Protocol Buffers (protobuf) specification** in the `kcl-lang/kcl` repository, the project enables thin, idiomatic language wrappers that share a single compiler implementation while respecting each language's memory management and type system conventions.

## Core Architecture: The Rust Foundation and C-ABI Layer

The architecture centers on three distinct layers that separate the compiler implementation from language-specific bindings.

### The Rust Core and Driver

The KCL compiler and runtime, responsible for parsing, type-checking, and evaluating KCL programs into JSON/YAML, resides entirely within the Rust codebase. In [`crates/driver/src/lib.rs`](https://github.com/kcl-lang/kcl/blob/main/crates/driver/src/lib.rs), the core compilation driver handles the heavy lifting of program execution. This crate serves as the engine that all language SDKs ultimately invoke, ensuring consistent behavior across every supported platform.

### The Stable C-API Interface

To bridge the gap between Rust and other languages, the repository exposes a stable **Application Binary Interface (ABI)** through [`crates/api/src/lib.rs`](https://github.com/kcl-lang/kcl/blob/main/crates/api/src/lib.rs). This file implements `extern "C"` functions—such as `kcl_load_files`—that compile to a shared library (`libkcl.so` on Linux, `.dylib` on macOS, `.dll` on Windows). These C functions provide a low-level, language-agnostic entry point that hides the complexity of Rust's ownership model while exposing essential lifecycle methods for session management and program execution.

### Protocol Buffer Specifications

Data exchange between the core and language SDKs follows a strict schema defined in `crates/api/spec.proto`. This protobuf spec describes the data model for KCL execution results, error messages, and RPC services. By standardizing on Protocol Buffers, KCL ensures that complex data structures serialize consistently across language boundaries, whether passed through FFI boundaries or transmitted via gRPC.

## Language-Specific Implementation Strategies

Each official SDK adopts the FFI strategy most idiomatic to its target language while sharing the same underlying C library and protobuf definitions.

### Rust SDK: Direct Native Linking

The **Rust SDK** (maintained in `kcl-lang/kcl-sdk-rust`) requires no Foreign Function Interface (FFI) overhead. It directly links to the `kcl-api` crate as a dependency, re-exporting the Rust API as idiomatic types through `kcl::api`. This approach eliminates marshaling costs and provides zero-cost abstractions over the core compiler functionality.

### Go SDK: CGO Bindings

The **Go SDK** (`kcl-lang/kcl-sdk-go`) utilizes **cgo** to import and call symbols from the shared `libkcl.so` library. The SDK maps Go structs to the protobuf message definitions, handling the conversion between Go's memory management and the C-ABI requirements. When you invoke methods like `ctx.LoadFile()`, the SDK marshals parameters across the cgo boundary, executes the corresponding `kcl_*` function, and deserializes the protobuf-encoded result into native Go structs.

### Python SDK: CFFI Integration

The **Python SDK** (`kcl-lang/kcl-sdk-py`) employs **cffi** (C Foreign Function Interface) or **ctypes** to dynamically load `libkcl.so` at runtime. This approach exposes high-level Python classes—such as `kcl.load()` and `kcl.run()`—that handle the low-level C function calls and protobuf deserialization transparently. Python dictionaries map directly to the protobuf message structures defined in `spec.proto`, allowing Pythonic access to KCL evaluation results.

## Execution Flow and Data Serialization

Understanding how a function call travels from application code to the Rust core clarifies the performance characteristics and error handling patterns.

### The Invocation Chain

When an SDK method executes—such as loading a KCL file—the call follows a predictable path:

1. **Language SDK** invokes a wrapper function (e.g., `LoadFile`)
2. **FFI Layer** marshals arguments through cgo (Go) or cffi (Python) into C-compatible types
3. **C-API** receives the call via `kcl_load_files` in [`crates/api/src/lib.rs`](https://github.com/kcl-lang/kcl/blob/main/crates/api/src/lib.rs)
4. **Rust Core** executes the compilation driver and returns protobuf-encoded bytes
5. **Deserialization** converts the bytes into language-native structures (Go structs, Python dicts, or Rust types)

### Optional gRPC Server Mode

Beyond direct FFI integration, KCL supports a **kcld** daemon that exposes the protobuf service over gRPC. In this mode, language SDKs can connect to a remote KCL instance rather than loading `libkcl.so` locally. This architecture proves useful for distributed build systems or scenarios requiring sandboxed execution, though it introduces network latency compared to in-process FFI calls.

## Implementation Examples

The following code snippets demonstrate the consistent API surface across languages, each performing the equivalent operation: loading a KCL file and serializing the result to JSON.

### Rust

```rust
use kcl_sdk::KclPackage;

fn main() -> anyhow::Result<()> {
    let pkg = KclPackage::load("example.k")?;
    let json = pkg.to_json()?;
    println!("{}", json);
    Ok(())
}

```

*Source: `kcl-lang/kcl-sdk-rust` examples*

### Go

```go
package main

import (
    "fmt"
    kcl "github.com/kcl-lang/kcl-sdk-go"
)

func main() {
    ctx, err := kcl.NewContext()
    if err != nil { panic(err) }
    
    pkg, err := ctx.LoadFile("example.k")
    if err != nil { panic(err) }
    
    jsonStr, err := pkg.ToJSON()
    if err != nil { panic(err) }
    
    fmt.Println(jsonStr)
}

```

*Source: `kcl-lang/kcl-sdk-go` examples*

### Python

```python
import kcl

pkg = kcl.load("example.k")
json_str = pkg.to_json()
print(json_str)

```

*Source: `kcl-lang/kcl-sdk-py` examples*

## Critical Source Files in kcl-lang/kcl

The following files constitute the single source of truth for the multi-language SDK architecture:

- **`crates/api/spec.proto`** – Defines the protobuf messages and service interfaces used by all SDKs for data exchange
- **[`crates/api/src/lib.rs`](https://github.com/kcl-lang/kcl/blob/main/crates/api/src/lib.rs)** – Implements the `extern "C"` functions that form the stable C-ABI, exported in `libkcl.so`
- **[`crates/driver/src/lib.rs`](https://github.com/kcl-lang/kcl/blob/main/crates/driver/src/lib.rs)** – Contains the core compilation driver invoked by the C-API layer
- **[`Cargo.toml`](https://github.com/kcl-lang/kcl/blob/main/Cargo.toml)** (workspace root) – Declares the `kcl-api` crate versioning that ensures SDK compatibility

## Summary

- **KCL's multi-language SDK architecture** centers on a Rust core that exposes a **stable C-API** and **Protocol Buffer specifications** through the `kcl-api` crate
- The **Rust SDK** links natively to the core crate, while **Go** uses **cgo** and **Python** uses **cffi** to interact with the shared `libkcl.so` library
- All language bindings share identical message definitions in `crates/api/spec.proto`, ensuring consistent serialization and behavior
- Execution follows a path from language-specific wrappers through FFI layers to `kcl_*` functions in [`crates/api/src/lib.rs`](https://github.com/kcl-lang/kcl/blob/main/crates/api/src/lib.rs), with results returned as protobuf-encoded bytes
- An optional **gRPC server mode** allows remote execution via the same protobuf interface used for local FFI calls

## Frequently Asked Questions

### Why does KCL use a C-API instead of direct Rust bindings for Go and Python?

The C-API provides a **stable Application Binary Interface (ABI)** that insulates language SDKs from internal Rust compiler changes, allowing the core to evolve without breaking Go or Python integrations. This approach avoids the complexity and compilation overhead of distributing Rust source code to non-Rust ecosystems. By compiling to a standard shared library (`libkcl.so`) with C linkage, KCL ensures maximum portability across operating systems and language runtimes.

### How does the KCL SDK architecture handle version compatibility between the core compiler and language bindings?

Version compatibility is enforced through the **`kcl-api` crate versioning** declared in the workspace [`Cargo.toml`](https://github.com/kcl-lang/kcl/blob/main/Cargo.toml) and the corresponding protobuf schema in `crates/api/spec.proto`. All three language SDKs target specific releases of the `libkcl.so` shared library, ensuring that message serialization formats and C function signatures remain synchronized. Developers must ensure that the installed shared library version matches the SDK version to prevent ABI mismatches during FFI calls.

### What is the performance overhead of using Go's cgo or Python's cffi compared to the native Rust SDK?

The **Rust SDK** incurs **zero FFI overhead** because it links directly to the native crate, while **Go's cgo** and **Python's cffi** introduce marginal latency primarily from crossing the language boundary and protobuf deserialization. In practice, this overhead is negligible compared to the cost of KCL compilation and evaluation, which dominates execution time. The optional **gRPC server mode** introduces additional network latency but eliminates local shared library dependencies.

### Can I use the KCL Python SDK without installing the Rust toolchain?

Yes, the **Python SDK** distributes pre-compiled shared libraries (`libkcl.so` or platform equivalents) via package managers like **pip**, allowing end users to install and run KCL without installing the Rust compiler. The `cffi` loader dynamically locates and loads the binary shared object at runtime, abstracting away the underlying Rust implementation. This distribution model mirrors the Go SDK approach, where users need only the compiled library, not the source code.