a70e68c7bd
* Smolmix documentation * Add smolmix docs: landing page, tutorials, and developer page links * Add Exit Gateway services page (NR vs IPR) and link from existing docs * Update auto-generated command and API outputs * Reorg of tutorials and architecture pages * License information + remove TODO from docs.rs visibile comment + reorg readme * Add versions file for doc-wide versioning * Relative -> absolute links * Relative -> absolute links * Update license + add old tutorial code as examples * Streamline smolmix docs * Clippy * Clean up doc comments * Last pass * Add larger file download to list * set new versions * Clippy * Remove blake pin from docs + add version range to root Cargo.toml * Format example logging * Remove crate blocked component * Loose whitespace * Add doc verification script for inline mdx * Formatting * Components regen * Reorg + tighten text * Voicing cohesion pass + remove bloated examples * Voicing cont. * Reduce max download size * Small suggested clarifications * Max/docs voicing consistency (#6769) * Reduce max download size * voicing consistency across docs * New landing order w smolmix * Tweaks * Final tweaks
106 lines
3.4 KiB
Plaintext
106 lines
3.4 KiB
Plaintext
---
|
|
title: "FFI Bindings: Go and C/C++"
|
|
description: "Use the Nym SDK from Go and C/C++ via FFI bindings. Covers mixnet messaging, anonymous replies, and TcpProxy lifecycle from non-Rust languages."
|
|
schemaType: "TechArticle"
|
|
section: "Developers"
|
|
lastUpdated: "2026-03-15"
|
|
---
|
|
|
|
# FFI Bindings
|
|
|
|
import { Callout } from 'nextra/components'
|
|
|
|
The SDK exposes FFI bindings for Go and C/C++. The source lives in [`sdk/ffi`](https://github.com/nymtech/nym/tree/develop/sdk/ffi):
|
|
|
|
```
|
|
ffi
|
|
├── cpp # C/C++ bindings (manual C FFI)
|
|
├── go # Go bindings (via uniffi-bindgen-go)
|
|
└── shared # Shared Rust implementation
|
|
```
|
|
|
|
Core logic lives in `shared/` and is imported into language-specific wrappers. The shared layer handles thread safety and runs client operations on blocking threads on the Rust side of the FFI boundary.
|
|
|
|
## What's exposed
|
|
|
|
**Mixnet** (Go and C/C++): ephemeral and persistent client creation, sending messages, anonymous replies via SURBs, listening for incoming messages.
|
|
|
|
**TcpProxy** (Go only): client and server creation and lifecycle.
|
|
|
|
<Callout type="warning">
|
|
The TcpProxy module is deprecated. For new projects, use the [Stream module](./stream) instead.
|
|
</Callout>
|
|
|
|
**Client Pool and Stream** have no standalone FFI bindings yet. The TcpProxy bindings use the Client Pool internally.
|
|
|
|
## Quick example (Go)
|
|
|
|
```go
|
|
// Initialise an ephemeral client
|
|
bindings.InitEphemeral()
|
|
|
|
// Get our Nym address
|
|
addr, _ := bindings.GetSelfAddress()
|
|
|
|
// Send a message through the Mixnet
|
|
bindings.SendMessage(addr, "hello from Go")
|
|
|
|
// Listen for incoming messages
|
|
msg, _ := bindings.ListenForIncoming()
|
|
fmt.Println("Received:", msg.Message)
|
|
|
|
// Reply anonymously via SURBs
|
|
bindings.Reply(msg.Sender, "reply from Go")
|
|
```
|
|
|
|
## Quick example (C++)
|
|
|
|
The C++ bindings use callbacks for return values and a `ReceivedMessage` struct for incoming data:
|
|
|
|
```cpp
|
|
extern "C" {
|
|
struct ReceivedMessage {
|
|
const uint8_t* message;
|
|
size_t size;
|
|
const char* sender_tag;
|
|
};
|
|
|
|
void init_logging();
|
|
char init_ephemeral();
|
|
char get_self_address(void (*callback)(const char*));
|
|
char send_message(const char*, const char*);
|
|
char listen_for_incoming(void (*callback)(ReceivedMessage));
|
|
char reply(const char*, const char*);
|
|
}
|
|
|
|
// Get address via callback
|
|
char addr[134];
|
|
void on_address(const char* s) { strcpy(addr, s); }
|
|
|
|
// Receive message via callback
|
|
char sender_tag[22];
|
|
void on_message(ReceivedMessage msg) {
|
|
std::cout << "Received: " << msg.message << std::endl;
|
|
strcpy(sender_tag, msg.sender_tag);
|
|
}
|
|
|
|
int main() {
|
|
init_ephemeral();
|
|
get_self_address(on_address);
|
|
send_message(addr, "hello from C++");
|
|
listen_for_incoming(on_message);
|
|
reply(sender_tag, "reply from C++");
|
|
}
|
|
```
|
|
|
|
## Building
|
|
|
|
Each language has a `build.sh` script that compiles the Rust shared library and generates bindings. See the README in each directory for prerequisites.
|
|
|
|
## Examples and source
|
|
|
|
- [Go mixnet example](https://github.com/nymtech/nym/blob/develop/sdk/ffi/go/example.go): init, send, receive, SURB reply
|
|
- [Go TcpProxy example](https://github.com/nymtech/nym/blob/develop/sdk/ffi/go/proxy_example.go): proxy client and server with TCP echo
|
|
- [C++ example](https://github.com/nymtech/nym/blob/develop/sdk/ffi/cpp/src/main.cpp): same flow using Boost threads
|
|
- [`sdk/ffi` source](https://github.com/nymtech/nym/tree/develop/sdk/ffi): full source and build scripts
|