--- 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. The TcpProxy module is deprecated. For new projects, use the [Stream module](./stream) instead. **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