librecast-sys 1.0.1

Low-level bindings to the librecast C library
Documentation
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
// Copyright (c) 2025 Gavin Henry <ghenry@sentrypeer.org>

// Ignore Rust's style conventions for our C FFI bindings
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]

// Use the include! macro to dump our generated bindings right into our crate's main entry point,
// src/lib.rs:
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));

// Some basic tests to ensure that our bindings are working as expected with
// the librecast C API

#[cfg(test)]
mod tests {
    use super::*;
    use std::ffi::{CStr, CString};

    #[test]
    fn test_lc_calls() {
        unsafe {
            // Create our context
            let lctx = lc_ctx_new();
            assert!(!lctx.is_null());

            // Create our socket
            let sock = lc_socket_new(lctx);
            assert!(!sock.is_null());

            // Create a Librecast channel
            let chan_name = CString::new("my very first Librecast channel")
                .expect("Failed to create CString for channel name");

            // Convert to a raw pointer for C API, which will be nicer in
            // our wrapper librecast crate
            let chan_name_c_string = chan_name.into_raw();

            let chan = lc_channel_new(lctx, chan_name_c_string);
            assert!(!chan.is_null());

            // Bind the channel to the socket
            lc_channel_bind(sock, chan);

            // Enable lookback, so we can receive our own packets on the same host
            lc_socket_loop(sock, 1);

            if !chan_name_c_string.is_null() {
                // Convert the raw pointer back to a CString to free it
                let _ = CStr::from_ptr(chan_name_c_string);
            }

            // Free the context. This also frees all Sockets, Channels, Routers etc.
            // created with that Context
            lc_ctx_free(lctx);
        }
    }
}