gl-sdk
Rust SDK for Greenlight with UniFFI bindings support.
Building
Build the library using Task:
Or directly with cargo from the workspace root:
Generating Language Bindings
Using Task (Recommended)
The easiest way to generate bindings is using the Task commands:
# Generate Python bindings
# Generate Kotlin bindings
# Generate Swift bindings
# Generate Ruby bindings
# Generate C++ bindings (requires uniffi-bindgen-cpp)
# Generate all language bindings
These commands work from any directory in the workspace.
Using uniffi-bindgen Directly
The project uses UniFFI to generate bindings for multiple languages from the UDL definition in src/sdk.udl.
The uniffi-bindgen tool is included in the workspace at libs/uniffi-bindgen.
Note: When using uniffi-bindgen directly, all commands must be run from the workspace root.
Generate Python Bindings
Generate Bindings for Other Languages
Replace --language python with:
kotlinfor Kotlinswiftfor Swiftrubyfor Ruby
Example for Kotlin:
Generate C++ Bindings
C++ bindings use uniffi-bindgen-cpp instead of the built-in uniffi-bindgen. Install it first:
Then build and generate bindings:
On Linux, replace
libglsdk.dylibwithlibglsdk.so.
The generated files require patching to avoid conflicts with the C++ reserved keyword register:
The task sdk:bindings-cpp command handles all of the above automatically, including platform detection.
Synchronous API Design
The entire public API exposed by the SDK through UniFFI is synchronous. Functions that need to perform async work (network I/O, gRPC calls) block the calling thread while an internal Tokio runtime executes the underlying async operations.
This is a deliberate design choice:
- Uniform bindings -- every target language (Python, Kotlin, Swift, Ruby, C++) gets the same blocking API. No language needs an async runtime, coroutine support, or special feature flags on the caller side.
- Simpler integration -- callers that need concurrency can use
their language's native threading primitives (e.g.
threadingin Python,std::threadin C++, coroutines in Kotlin) to call SDK methods off the main thread. - No conditional compilation -- a single build of the shared library works for all bindings, avoiding feature-flag divergence between languages.
The internal Tokio runtime is created lazily on the first call and
lives for the lifetime of the process (see src/util.rs).
Files
src/sdk.udl- UniFFI interface definitionbuild.rs- Build script that generates Rust scaffoldingbindings/- Generated language bindings (created by uniffi-bindgen)