diff --git a/example/main/Cargo.toml b/example/main/Cargo.toml index 4967cc6..7b590c7 100644 --- a/example/main/Cargo.toml +++ b/example/main/Cargo.toml @@ -25,7 +25,7 @@ edition = "2021" default-run = "main" [dependencies] -libloading = "0.8.1" +libloading = "0.8.3" trixy = { path = "../../." } [build-dependencies] diff --git a/example/main/Makefile b/example/main/Makefile index cea6907..e673702 100644 --- a/example/main/Makefile +++ b/example/main/Makefile @@ -22,7 +22,8 @@ BIN_NAME := ./target/plugin.so BUILD_DIR := ./target/c_build/ -SRC := $(wildcard c/*.c) +# SRC := $(wildcard c/*.c) +SRC := c/main.c OBJ := $(SRC:.c=.o) DEP := $(OBJ:.o=.d) diff --git a/example/main/build.rs b/example/main/build.rs index 8ef17a9..5d53eea 100644 --- a/example/main/build.rs +++ b/example/main/build.rs @@ -20,15 +20,15 @@ * If not, see . */ -use trixy::macros::config::TrixyConfig; +use trixy::macros::config::trixy::TrixyConfig; fn main() { println!("cargo:rerun-if-changed=./dist/*"); println!("cargo:rerun-if-changed=./src/bin/main/api.tri"); println!("cargo:rerun-if-changed=./src/bin/main/trinitrix_api.tri"); - TrixyConfig::new("handle_cmd") - .trixy_path("./src/bin/main/trinitrix_api.tri") + let file_tree = TrixyConfig::new("handle_cmd") + .trixy_path("./src/bin/main/api.tri") .dist_dir_path("./dist") - .generate_debug(true) .generate(); + file_tree.materialize().unwrap(); } diff --git a/example/main/c/main.c b/example/main/c/main.c index 922ce3d..5de1453 100644 --- a/example/main/c/main.c +++ b/example/main/c/main.c @@ -47,6 +47,21 @@ handle_error () free (error); } +struct Dog +guess (const char *pers_name, uint32_t age) +{ + println ("Rust wants to name the dog %s, but that's not good!", pers_name); + + // The callback must free all its owned arguments, as rust just moved these + // here and is not going to free them. + string_free (pers_name); + + struct Dog dog = { + .name = "James", + }; + return dog; +} + int plugin_main () { @@ -64,7 +79,7 @@ plugin_main () println ("Saying hi!"); const char *hi; - if (!one.hi (&hi, "Adam")) + if (!dogs.hi (&hi, "Adam")) handle_error (); println ("Rust returned: %s", hi); @@ -74,7 +89,7 @@ plugin_main () // types are defined in the `api.tri` file) struct Dog dog = { .name = "Bruce" }; struct TrainedDog tDog; - if (!one.train_dog (&tDog, dog)) + if (!dogs.train_dog (&tDog, dog)) handle_error (); println ("Dog %s is now trained with specialization %i", tDog.name, @@ -82,5 +97,11 @@ plugin_main () // Beware that you need to free them with the appropriate free functions string_free (tDog.name); + // Trixy also supports functions (i.e. callbacks): + enum DogType output_dog; + if (!dogs.guess_my_favourite_dog (&output_dog, guess)) + handle_error (); + println ("Rust guessed %d", output_dog); + return 0; } diff --git a/example/main/c/trinitrix.c b/example/main/c/trinitrix.c new file mode 100644 index 0000000..a50866d --- /dev/null +++ b/example/main/c/trinitrix.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2023 - 2024: + * The Trinitrix Project + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * This file is part of the Trixy crate for Trinitrix. + * + * Trixy is free software: you can redistribute it and/or modify + * it under the terms of the Lesser GNU General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * and the Lesser GNU General Public License along with this program. + * If not, see . + */ + +#include "../dist/interface.h" +#include +#include +#include +#include + +#define println(args...) \ + printf ("\33[32;1m(plugin):\33[0m \33[34;1m"); \ + printf (args); \ + printf ("\n\33[0m"); \ + fflush (stdout); +#define eprintln(args...) \ + printf ("\33[32;1m(plugin):\33[0m\33[31;1m "); \ + printf (args); \ + printf ("\n\33[0m"); \ + fflush (stdout); + +void +handle_error () +{ + int error_length = last_error_length (); + char *error = malloc (error_length); + last_error_message (error, error_length); + eprintln ("Encountered error: %s", error); + free (error); +} + +int +plugin_main () +{ + if (!trinitrix.api.room_message_send ("Hi!")) + handle_error (); + return EXIT_SUCCESS; +} diff --git a/example/main/src/bin/main/api.tri b/example/main/src/bin/main/api.tri index 26d6bd0..8b77d96 100644 --- a/example/main/src/bin/main/api.tri +++ b/example/main/src/bin/main/api.tri @@ -37,7 +37,21 @@ enum TrainingMistake { Died, } -mod one { +struct Dog { + name: String, +} + +mod dogs { + /// The possible types a dog can have + /// + /// Beware that [`DogType::Cat`] and [`DogType::Lion`] are not really recognized as + /// dogs. + enum DogType { + Akita, + Cat, + Lion, + } + /// A Dog after extensive training struct TrainedDog { name: String, @@ -46,15 +60,10 @@ mod one { /// Say hi to a name fn hi(name: String) -> String; - /// Train a dog without using any resources - // fn cheaply_train_dog(dog: Dog) -> Result; - /// Train a dog fn train_dog(dog: Dog) -> TrainedDog; -} -struct Dog { - name: String, + fn guess_my_favourite_dog(callback: fn(name: String, age: u32) -> Dog) -> DogType; } // Trixy is a subset of Rust diff --git a/example/main/src/bin/main/main.rs b/example/main/src/bin/main/main.rs index 126f1b2..9f6e296 100644 --- a/example/main/src/bin/main/main.rs +++ b/example/main/src/bin/main/main.rs @@ -22,8 +22,11 @@ use std::{env, ffi::c_int, mem}; +use dogs::TrainedDog; use libloading::{Library, Symbol}; +use crate::dogs::DogType; + include!(concat!(env!("OUT_DIR"), "/api.rs")); // run `cargo r --bin api > ./src/bin/main/api.rs` to output the generated api @@ -32,13 +35,37 @@ include!(concat!(env!("OUT_DIR"), "/api.rs")); fn handle_cmd(cmd: Commands) { match cmd { - Commands::One(one) => match one { - one::One::hi { trixy_output, name } => { + Commands::Dogs(one) => match one { + dogs::Dogs::hi { trixy_output, name } => { let output = format!("Hi {}!", name); println!("(rust): {}", output); trixy_output.send(output.into()).expect("Will work"); mem::forget(name); } + dogs::Dogs::train_dog { trixy_output, dog } => { + trixy_output + .send( + TrainedDog { + name: "Willis".into(), + training: DogTraining::Wolf, + } + .try_into() + .unwrap(), + ) + .unwrap(); + mem::forget(dog); + } + dogs::Dogs::guess_my_favourite_dog { + trixy_output, + callback, + } => { + let fav_dog = callback("Frank".into(), 30); + let dog_name: String = fav_dog.name.clone().try_into().unwrap(); + println!("(rust): They want a dog named: {}", dog_name); + trixy_output.send(DogType::Cat.into()).unwrap(); + + mem::forget(dog_name); + } }, Commands::outstanding { name } => { println!("(rust): {} is outstanding!", name); diff --git a/example/main/src/bin/main/trinitrix_api.tri b/example/main/src/bin/main/trinitrix_api.tri new file mode 120000 index 0000000..83efdf9 --- /dev/null +++ b/example/main/src/bin/main/trinitrix_api.tri @@ -0,0 +1 @@ +../../../../../tests/trinitrix_api/input.tri \ No newline at end of file