From 57068747de51315cf9aca19f722cbca986070962 Mon Sep 17 00:00:00 2001 From: Ivan FB <128452529+Ivansete-status@users.noreply.github.com> Date: Mon, 26 Feb 2024 16:48:05 +0100 Subject: [PATCH] chore(cbindings): cbindings rust simple libwaku integration example (#2089) --- .gitignore | 2 + examples/rust/Cargo.lock | 25 +++++++++ examples/rust/Cargo.toml | 9 +++ examples/rust/README.md | 6 ++ examples/rust/build.rs | 5 ++ examples/rust/src/main.rs | 114 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 161 insertions(+) create mode 100644 examples/rust/Cargo.lock create mode 100644 examples/rust/Cargo.toml create mode 100644 examples/rust/README.md create mode 100644 examples/rust/build.rs create mode 100644 examples/rust/src/main.rs diff --git a/.gitignore b/.gitignore index bba92fab8..7f69ad741 100644 --- a/.gitignore +++ b/.gitignore @@ -57,6 +57,8 @@ nimbus-build-system.paths *.sqlite3-wal /examples/nodejs/build/ +/examples/rust/target/ + # Coverage coverage_html_report/ diff --git a/examples/rust/Cargo.lock b/examples/rust/Cargo.lock new file mode 100644 index 000000000..a4fea40be --- /dev/null +++ b/examples/rust/Cargo.lock @@ -0,0 +1,25 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "libc" +version = "0.2.148" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" + +[[package]] +name = "waku-rust-simple-example" +version = "0.1.0" +dependencies = [ + "cc", +] diff --git a/examples/rust/Cargo.toml b/examples/rust/Cargo.toml new file mode 100644 index 000000000..c9ad9faa4 --- /dev/null +++ b/examples/rust/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "waku-rust-simple-example" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[build-dependencies] +cc = "1.0.52" diff --git a/examples/rust/README.md b/examples/rust/README.md new file mode 100644 index 000000000..dc7bce305 --- /dev/null +++ b/examples/rust/README.md @@ -0,0 +1,6 @@ + +This represents a very simple example on how to integrate the `libwaku` library in Rust, and then, only a few `libwaku` functions are being wrapped. + +In [waku-rust-bindings](https://github.com/waku-org/waku-rust-bindings) you will find a complete Waku integration in Rust. + + diff --git a/examples/rust/build.rs b/examples/rust/build.rs new file mode 100644 index 000000000..b0398c6ee --- /dev/null +++ b/examples/rust/build.rs @@ -0,0 +1,5 @@ + +fn main() { + println!("cargo:rustc-link-arg=-lwaku"); + println!("cargo:rustc-link-arg=-L../../build/"); +} diff --git a/examples/rust/src/main.rs b/examples/rust/src/main.rs new file mode 100644 index 000000000..1580bfb4b --- /dev/null +++ b/examples/rust/src/main.rs @@ -0,0 +1,114 @@ + +use std::os::raw::{c_char, c_int, c_void}; +use std::{slice, thread, time}; +use std::cell::OnceCell; +use std::ffi::CString; + +pub type WakuCallback = + unsafe extern "C" fn( + c_int, + *const c_char, + usize, + *const c_void, + ); + +extern "C" { + pub fn waku_new( + config_json: *const u8, + cb: WakuCallback, + user_data: *const c_void, + ) -> *mut c_void; + + pub fn waku_version( + ctx: *const c_void, + cb: WakuCallback, + user_data: *const c_void, + ) -> c_int; + + pub fn waku_default_pubsub_topic( + ctx: *mut c_void, + cb: WakuCallback, + user_data: *const c_void, + ) -> *mut c_void; +} + +pub unsafe extern "C" fn trampoline( + return_val: c_int, + buffer: *const c_char, + buffer_len: usize, + data: *const c_void, +) where + C: FnMut(i32, &str), +{ + let closure = &mut *(data as *mut C); + + let buffer_utf8 = + String::from_utf8(slice::from_raw_parts(buffer as *mut u8, buffer_len) + .to_vec()) + .expect("valid utf8"); + + closure(return_val, &buffer_utf8); +} + +pub fn get_trampoline(_closure: &C) -> WakuCallback +where + C: FnMut(i32, &str), +{ + trampoline:: +} + +fn main() { + let config_json = "\ + { \ + \"host\": \"127.0.0.1\",\ + \"port\": 60000, \ + \"key\": \"0d714a1fada214dead6dc9c7274581ec20ff292451866e7d6d677dc818e8ccd2\", \ + \"relay\": true \ + }"; + + unsafe { + // Create the waku node + let closure = |ret: i32, data: &str| { + println!("Ret {ret}. Error creating waku node {data}"); + }; + let cb = get_trampoline(&closure); + let config_json_str = CString::new(config_json).unwrap(); + let ctx = waku_new( + config_json_str.as_ptr() as *const u8, + cb, + &closure as *const _ as *const c_void, + ); + + // Extracting the current waku version + let version: OnceCell = OnceCell::new(); + let closure = |ret: i32, data: &str| { + println!("version_closure. Ret: {ret}. Data: {data}"); + let _ = version.set(data.to_string()); + }; + let cb = get_trampoline(&closure); + let _ret = waku_version( + &ctx as *const _ as *const c_void, + cb, + &closure as *const _ as *const c_void, + ); + + // Extracting the default pubsub topic + let default_pubsub_topic: OnceCell = OnceCell::new(); + let closure = |_ret: i32, data: &str| { + let _ = default_pubsub_topic.set(data.to_string()); + }; + let cb = get_trampoline(&closure); + let _ret = waku_default_pubsub_topic( + ctx, + cb, + &closure as *const _ as *const c_void, + ); + + println!("Version: {}", version.get_or_init(|| unreachable!())); + println!("Default pubsubTopic: {}", default_pubsub_topic.get_or_init(|| unreachable!())); + } + + loop { + thread::sleep(time::Duration::from_millis(10000)); + } +}