HKalbasi / zngur

A C++/Rust interop tool
https://hkalbasi.github.io/zngur
Apache License 2.0
236 stars 4 forks source link

Using Rust type implementing custom traits in C++ #4

Open ttzytt opened 1 month ago

ttzytt commented 1 month ago

I was trying to expose the following types to C++ types. I directly added them in /examples/tutorial:

pub trait Animal{
    fn make_sound(&self);
}

impl Animal for Dog {
    fn make_sound(&self) {
        println!("{} says woof", self.name);
    }
}
pub struct Dog {
    name : String,
}

The .zng configs are shown below:

trait crate::Animal{
    fn make_sound(&self);
}

type crate::Dog{
    #layout(size = 24, align = 8);    
    fn make_sound(&self);
}

However, I'm getting the following errors:

error[E0599]: no function or associated item named `make_sound` found for struct `Dog` in the current scope
   --> examples/tutorial/src/generated.rs:204:51
    |
204 |     ::std::ptr::write(o as *mut (), <crate::Dog>::make_sound::<>(::std::ptr::read(i0 as *mut &crate::Dog), ));
    |                                                   ^^^^^^^^^^ function or associated item not found in `Dog`
    |
   ::: examples/tutorial/src/lib.rs:55:1
    |
55  | pub struct Dog {
    | -------------- function or associated item `make_sound` not found for this struct
    |
    = help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
    |
2   + use crate::Animal;
    |

For more information about this error, try `rustc --explain E0599`.
error: could not compile `example-tutorial` (lib) due to previous error
make: *** [Makefile:5: ../../target/release/libexample_tutorial.a] Error 101

I'm wondering why this is happening. Did I use the .zng file wrongly, or is this feature currently not yet supported?

HKalbasi commented 1 month ago

You should add an use for the trait for now:

type crate::Dog{
    #layout(size = 24, align = 8);    
    fn make_sound(&self) use crate::Animal;
}

See the rayon example for more usage examples.

ttzytt commented 1 month ago

Thanks, but it seems like there still exist problems after this change:

cargo build --release
    Finished release [optimized] target(s) in 0.01s
g++ main.cpp -g -L ../../target/release/ -l example_tutorial
/usr/bin/ld: ../../target/release//libexample_tutorial.a(example_tutorial-e331c2f8d22efcbe.example_tutorial.a3c52e8e-cgu.7.rcgu.o): in function `<example_tutorial::generated::__zngur_crate_Animal_s13::Wrapper as example_tutorial::Animal>::make_sound':
example_tutorial.a3c52e8e-cgu.7:(.text._ZN107_$LT$example_tutorial..generated..__zngur_crate_Animal_s13..Wrapper$u20$as$u20$example_tutorial..Animal$GT$10make_sound17hd467e9831d615ffaE+0x9): undefined reference to `__zngur_crate_Animal_s13_make_sound'
/usr/bin/ld: ../../target/release//libexample_tutorial.a(example_tutorial-e331c2f8d22efcbe.example_tutorial.a3c52e8e-cgu.7.rcgu.o): in function `<example_tutorial::generated::__zngur_crate_Animal_s13_borrowed::Wrapper as example_tutorial::Animal>::make_sound':
example_tutorial.a3c52e8e-cgu.7:(.text._ZN116_$LT$example_tutorial..generated..__zngur_crate_Animal_s13_borrowed..Wrapper$u20$as$u20$example_tutorial..Animal$GT$10make_sound17hc11122528f296618E+0x6): undefined reference to `__zngur_crate_Animal_s13_make_sound'
collect2: error: ld returned 1 exit status
make: *** [Makefile:2: a.out] Error 1
HKalbasi commented 1 month ago

I can't reproduce the error. Here is my exact diff:

diff --git a/examples/tutorial/main.cpp b/examples/tutorial/main.cpp
index 28bf25c..4e32545 100644
--- a/examples/tutorial/main.cpp
+++ b/examples/tutorial/main.cpp
@@ -9,4 +9,7 @@ int main() {

   rust::std::vec::Vec<rust::crate::Item> v = inventory.into_items();
   zngur_dbg(v);
+
+  auto dog = rust::crate::Dog(rust::Str::from_char_star("woofy").to_owned());
+  dog.make_sound();
 }
diff --git a/examples/tutorial/main.zng b/examples/tutorial/main.zng
index 4fce07b..cabfbfa 100644
--- a/examples/tutorial/main.zng
+++ b/examples/tutorial/main.zng
@@ -33,3 +33,11 @@ type crate::Inventory {
     fn add_item(&mut self, crate::Item);
     fn into_items(self) -> ::std::vec::Vec<crate::Item>;
 }
+
+type crate::Dog {
+    #layout(size = 24, align = 8);    
+
+    constructor { name: ::std::string::String };
+
+    fn make_sound(&self) use crate::Animal;
+}
diff --git a/examples/tutorial/src/lib.rs b/examples/tutorial/src/lib.rs
index 15584e9..fb0389e 100644
--- a/examples/tutorial/src/lib.rs
+++ b/examples/tutorial/src/lib.rs
@@ -40,3 +40,16 @@ impl Inventory {
         self.items
     }
 }
+
+pub trait Animal {
+    fn make_sound(&self);
+}
+
+impl Animal for Dog {
+    fn make_sound(&self) {
+        println!("{} says woof", self.name);
+    }
+}
+pub struct Dog {
+    name: String,
+}

Which works for me when I run make && ./a.out and prints woofy says woof. cargo build --release also works and doesn't produce the linker error you have been hit, but it only builds the rust static library so you can't execute its result.