diff --git a/Cargo.lock b/Cargo.lock index dd3bf953..32e5a827 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -746,17 +746,6 @@ dependencies = [ "syn", ] -[[package]] -name = "cxx-dataflow-example-node-rust-api" -version = "0.1.0" -dependencies = [ - "cxx", - "cxx-build", - "dora-node-api", - "eyre", - "rand", -] - [[package]] name = "cxx-dataflow-example-operator-rust-api" version = "0.1.0" @@ -1007,6 +996,16 @@ dependencies = [ "tracing", ] +[[package]] +name = "dora-node-api-cxx" +version = "0.1.0" +dependencies = [ + "cxx", + "cxx-build", + "dora-node-api", + "eyre", +] + [[package]] name = "dora-node-api-python" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 3438425c..5075bf1d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [workspace] members = [ "apis/c/*", + "apis/c++/*", "apis/python/node", "apis/python/operator", "apis/rust/*", @@ -8,7 +9,7 @@ members = [ "apis/rust/operator/types", "binaries/*", "examples/rust-dataflow/*", - "examples/c++-dataflow/*-rust-*", + "examples/c++-dataflow/operator-rust-api", "examples/iceoryx/*", "libraries/communication-layer", "libraries/core", diff --git a/examples/c++-dataflow/node-rust-api/Cargo.toml b/apis/c++/node/Cargo.toml similarity index 70% rename from examples/c++-dataflow/node-rust-api/Cargo.toml rename to apis/c++/node/Cargo.toml index 042f8f92..3b7ab157 100644 --- a/examples/c++-dataflow/node-rust-api/Cargo.toml +++ b/apis/c++/node/Cargo.toml @@ -1,15 +1,19 @@ [package] -name = "cxx-dataflow-example-node-rust-api" +name = "dora-node-api-cxx" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lib] +crate-type = ["staticlib"] + [dependencies] cxx = "1.0.73" -dora-node-api = { version = "0.1.0", path = "../../../apis/rust/node" } +dora-node-api = { version = "0.1.0", path = "../../../apis/rust/node", default-features = false, features = [ + "zenoh", +] } eyre = "0.6.8" -rand = "0.8.5" [build-dependencies] cxx-build = "1.0.73" diff --git a/apis/c++/node/build.rs b/apis/c++/node/build.rs new file mode 100644 index 00000000..dba00707 --- /dev/null +++ b/apis/c++/node/build.rs @@ -0,0 +1,4 @@ +fn main() { + let _build = cxx_build::bridge("src/lib.rs"); + println!("cargo:rerun-if-changed=src/lib.rs"); +} diff --git a/examples/c++-dataflow/node-rust-api/src/main.rs b/apis/c++/node/src/lib.rs similarity index 50% rename from examples/c++-dataflow/node-rust-api/src/main.rs rename to apis/c++/node/src/lib.rs index 30d37d24..a963017e 100644 --- a/examples/c++-dataflow/node-rust-api/src/main.rs +++ b/apis/c++/node/src/lib.rs @@ -1,7 +1,12 @@ -use dora_node_api::{self, DoraNode, Input, Receiver}; +use dora_node_api::{self, Input, Receiver}; #[cxx::bridge] mod ffi { + struct DoraNode { + inputs: Box, + send_output: Box, + } + struct DoraInput { end_of_input: bool, id: String, @@ -14,22 +19,38 @@ mod ffi { extern "Rust" { type Inputs; - type OutputSender<'a>; + type OutputSender; - fn next_input(inputs: &mut Inputs) -> DoraInput; - fn send_output(output_sender: &mut OutputSender, id: String, data: &[u8]) -> DoraResult; + fn init_dora_node() -> Result; + fn free_dora_node(node: DoraNode); + fn next_input(inputs: &mut Box) -> DoraInput; + fn send_output( + output_sender: &mut Box, + id: String, + data: &[u8], + ) -> DoraResult; } +} - unsafe extern "C++" { - include!("cxx-dataflow-example-node-rust-api/src/main.h"); +fn init_dora_node() -> eyre::Result { + let mut node = dora_node_api::DoraNode::init_from_env()?; + let input_stream = node.inputs()?; + let inputs = Inputs(input_stream); + let send_output = OutputSender(node); - fn cxx_main(inputs: &mut Inputs, output_sender: &mut OutputSender); - } + Ok(ffi::DoraNode { + inputs: Box::new(inputs), + send_output: Box::new(send_output), + }) +} + +fn free_dora_node(node: ffi::DoraNode) { + let _ = node; } pub struct Inputs(Receiver); -fn next_input(inputs: &mut Inputs) -> ffi::DoraInput { +fn next_input(inputs: &mut Box) -> ffi::DoraInput { match inputs.0.recv() { Ok(input) => { let id = input.id.clone().into(); @@ -48,9 +69,9 @@ fn next_input(inputs: &mut Inputs) -> ffi::DoraInput { } } -pub struct OutputSender<'a>(&'a mut DoraNode); +pub struct OutputSender(dora_node_api::DoraNode); -fn send_output(sender: &mut OutputSender, id: String, data: &[u8]) -> ffi::DoraResult { +fn send_output(sender: &mut Box, id: String, data: &[u8]) -> ffi::DoraResult { let result = sender .0 .send_output(&id.into(), Default::default(), data.len(), |out| { @@ -62,13 +83,3 @@ fn send_output(sender: &mut OutputSender, id: String, data: &[u8]) -> ffi::DoraR }; ffi::DoraResult { error } } - -fn main() -> eyre::Result<()> { - let mut node = DoraNode::init_from_env()?; - let input_stream = node.inputs()?; - let mut inputs = Inputs(input_stream); - let mut outputs = OutputSender(&mut node); - ffi::cxx_main(&mut inputs, &mut outputs); - - Ok(()) -} diff --git a/examples/c++-dataflow/dataflow.yml b/examples/c++-dataflow/dataflow.yml index 23caf7cc..ffa0f061 100644 --- a/examples/c++-dataflow/dataflow.yml +++ b/examples/c++-dataflow/dataflow.yml @@ -5,7 +5,7 @@ communication: nodes: - id: cxx-node-rust-api custom: - source: ../../target/debug/cxx-dataflow-example-node-rust-api + source: build/node_rust_api inputs: tick: dora/timer/millis/300 outputs: diff --git a/examples/c++-dataflow/node-rust-api/build.rs b/examples/c++-dataflow/node-rust-api/build.rs deleted file mode 100644 index 82011d84..00000000 --- a/examples/c++-dataflow/node-rust-api/build.rs +++ /dev/null @@ -1,10 +0,0 @@ -fn main() { - cxx_build::bridge("src/main.rs") // returns a cc::Build - .file("src/main.cc") - .flag_if_supported("-std=c++14") - .compile("cxx-example-dataflow-node"); - - println!("cargo:rerun-if-changed=src/main.rs"); - println!("cargo:rerun-if-changed=src/main.cc"); - println!("cargo:rerun-if-changed=src/main.h"); -} diff --git a/examples/c++-dataflow/node-rust-api/src/main.cc b/examples/c++-dataflow/node-rust-api/main.cc similarity index 70% rename from examples/c++-dataflow/node-rust-api/src/main.cc rename to examples/c++-dataflow/node-rust-api/main.cc index 97815ac0..3490d5a3 100644 --- a/examples/c++-dataflow/node-rust-api/src/main.cc +++ b/examples/c++-dataflow/node-rust-api/main.cc @@ -1,20 +1,22 @@ -#include "cxx-dataflow-example-node-rust-api/src/main.h" +#include "../build/dora-node-api.h" #include #include -void cxx_main(Inputs &inputs, OutputSender &output_sender) +int main() { std::cout << "HELLO FROM C++" << std::endl; unsigned char counter = 0; + auto dora_node = init_dora_node(); + for (int i = 0; i < 20; i++) { - auto input = next_input(inputs); + auto input = next_input(dora_node.inputs); if (input.end_of_input) { - return; + break; } counter += 1; @@ -22,12 +24,14 @@ void cxx_main(Inputs &inputs, OutputSender &output_sender) std::vector out_vec{counter}; rust::Slice out_slice{out_vec.data(), out_vec.size()}; - auto result = send_output(output_sender, "counter", out_slice); + auto result = send_output(dora_node.send_output, "counter", out_slice); auto error = std::string(result.error); if (!error.empty()) { std::cerr << "Error: " << error << std::endl; - return; + return -1; } } + + return 0; } diff --git a/examples/c++-dataflow/node-rust-api/src/main.h b/examples/c++-dataflow/node-rust-api/src/main.h deleted file mode 100644 index 5420f18b..00000000 --- a/examples/c++-dataflow/node-rust-api/src/main.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -#include "cxx-dataflow-example-node-rust-api/src/main.rs.h" - -void cxx_main(Inputs &inputs, OutputSender &output_sender); diff --git a/examples/c++-dataflow/run.rs b/examples/c++-dataflow/run.rs index c4daf9b3..594beb8c 100644 --- a/examples/c++-dataflow/run.rs +++ b/examples/c++-dataflow/run.rs @@ -8,20 +8,46 @@ use std::{ #[tokio::main] async fn main() -> eyre::Result<()> { let root = Path::new(env!("CARGO_MANIFEST_DIR")); + let target = root.join("target"); std::env::set_current_dir(root.join(file!()).parent().unwrap()) .wrap_err("failed to set working dir")?; tokio::fs::create_dir_all("build").await?; + let build_dir = Path::new("build"); - build_package("cxx-dataflow-example-node-rust-api").await?; build_package("cxx-dataflow-example-operator-rust-api").await?; + build_package("dora-node-api-cxx").await?; + let cxxbridge = target + .join("cxxbridge") + .join("dora-node-api-cxx") + .join("src"); + tokio::fs::copy(cxxbridge.join("lib.rs.cc"), build_dir.join("bridge.cc")).await?; + tokio::fs::copy( + cxxbridge.join("lib.rs.h"), + build_dir.join("dora-node-api.h"), + ) + .await?; + build_package("dora-node-api-c").await?; build_package("dora-operator-api-c").await?; build_cxx_node( root, - &dunce::canonicalize(Path::new("node-c-api").join("main.cc"))?, + &[ + &dunce::canonicalize(Path::new("node-rust-api").join("main.cc"))?, + &dunce::canonicalize(build_dir.join("bridge.cc"))?, + ], + "node_rust_api", + &["-l", "dora_node_api_cxx"], + ) + .await?; + build_cxx_node( + root, + &[&dunce::canonicalize( + Path::new("node-c-api").join("main.cc"), + )?], "node_c_api", + &["-l", "dora_node_api_c"], ) .await?; build_cxx_operator( @@ -52,11 +78,16 @@ async fn build_package(package: &str) -> eyre::Result<()> { Ok(()) } -async fn build_cxx_node(root: &Path, path: &Path, out_name: &str) -> eyre::Result<()> { +async fn build_cxx_node( + root: &Path, + paths: &[&Path], + out_name: &str, + args: &[&str], +) -> eyre::Result<()> { let mut clang = tokio::process::Command::new("clang++"); - clang.arg(path); - clang.arg("-std=c++14"); - clang.arg("-l").arg("dora_node_api_c"); + clang.args(paths); + clang.arg("-std=c++17"); + clang.args(args); #[cfg(target_os = "linux")] { clang.arg("-l").arg("m"); @@ -110,7 +141,7 @@ async fn build_cxx_node(root: &Path, path: &Path, out_name: &str) -> eyre::Resul clang .arg("--output") .arg(Path::new("../build").join(format!("{out_name}{EXE_SUFFIX}"))); - if let Some(parent) = path.parent() { + if let Some(parent) = paths[0].parent() { clang.current_dir(parent); } @@ -125,7 +156,7 @@ async fn build_cxx_operator(path: &Path, out_name: &str) -> eyre::Result<()> { let mut compile = tokio::process::Command::new("clang++"); compile.arg("-c").arg(path); - compile.arg("-std=c++14"); + compile.arg("-std=c++17"); compile.arg("-o").arg(&object_file_path); #[cfg(unix)] compile.arg("-fPIC");