Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ CLI tool to generate bindings for WIT documents and the component model.

[workspace]
members = [
"crates/test-rust-wasm",
]
"crates/test-rust-wasm","crates/cpp/tests/native_strings/rust-host/rust_native_host_lib","crates/cpp/tests/native_strings/rust-host/rust_app"]
resolver = "2"

[workspace.package]
Expand Down
1 change: 1 addition & 0 deletions crates/cpp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ description = """
C++ guest and host binding generator for WIT and the component model.
"""


[lib]
doctest = false
test = false
Expand Down
28 changes: 17 additions & 11 deletions crates/cpp/tests/native_strings/Makefile
Original file line number Diff line number Diff line change
@@ -1,30 +1,36 @@
CXXFLAGS=-g -O0 -I../../helper-types
CXXFLAGS=-g -O0 -I../../helper-types -I../../cpp_host -I../../guest --std=c++17
WIT_BINDGEN=../../../../target/debug/wit-bindgen

all: libstrings.so app-strings
all: libstrings.so cpp-app-strings rust-app-strings

libstrings.so: the_world.pie.o guest.pie.o
$(CXX) $(CXXFLAGS) -shared -o $@ $^ -Wl,--version-script=guest.lds
libstrings.so:
cd guest && make $@

%.pie.o: %.cpp
$(CXX) $(CXXFLAGS) -fPIE -o $@ -c $^
cpp-app-strings: ./cpp_host/the_world_native.o main.o ./cpp_host/guest_imported_fns.o
$(CXX) $(CXXFLAGS) -o $@ $^ -g -L./guest -lstrings

app-strings: the_world_native.o main.o
$(CXX) $(CXXFLAGS) -o $@ $^ -L. -lstrings
rust-app-strings: main.o
$(CXX) $(CXXFLAGS) -o $@ $^ -g -L/mnt/sda2/pradeep/wasm/RND/math_fns/target/debug -lstrings


the_world_native.o:
cd cpp_host && make $@

bindgen: wit/strings.wit
$(WIT_BINDGEN) cpp wit --wasm64 --format
$(WIT_BINDGEN) cpp wit --wasm64 --format --direct
cd rust/src ; ../../$(WIT_BINDGEN) rust ../../wit --wasm64

guest.wasm: the_world.cpp guest.cpp
guest.wasm: the_world.cpp guest_1.cpp
/opt/wasi-sdk/bin/clang++ -o $@ $^ $(CXXFLAGS)

guest_release.wasm: the_world.cpp guest.cpp
guest_release.wasm: the_world.cpp guest_1.cpp
/opt/wasi-sdk/bin/clang++ -o $@ $^ $(CXXFLAGS) -g0 -O3

clean:
-rm *.o libstrings.so app-strings
-rm *.o app-strings
cd guest && make clean
cd cpp_host && make clean

run:
LD_LIBRARY_PATH=. ./app-strings
Expand Down
50 changes: 50 additions & 0 deletions crates/cpp/tests/native_strings/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Native string example

In this example, there is a guest, a native host (cpp_host) and an application.
The `guest + native host` together form the actual `guest` code, which exports some APIs.
Now the application which is `host`, will use the guest exported calls.
The application/host also imports some calls, those are part of the `guest_imported_functions.cpp`

The directory strucutre is as below:
```
├── cpp_host (Native host code)
├── guest (Guest code)
├── guest_imported_fns.cpp ( host application imported calls)
├── main.cpp (Application)
└── wit (Wit file that is used for generating the code)

```

# Call-graph for a function
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for creating this!


This is how the example works, call graph for the function `A` (communication between the guest_1 and guest_2 using the mesh/native host code)

guest_1->exports::foo::foo::strings::A(a){native host export call}->fooX3AfooX2FstringsX23a(){native host export binding(lifting)}
-> exports::foo::foo::strings::A(wit::string &&x){guest_1 export implementation}
-> foo::foo::strings::A(std::string_view x){guest import call}->fooX3AfooX2FstringsX00a() {native host import binding(lowering)}
-> foo::foo::strings::A(std::string_view x) { guest import functions implementation}

# Building the rust native string app
Here is the rust based native string application source code tree
```
├── rust_app (Application that uses the native rust code)
│ ├── Cargo.toml
│ └── src
│ └── main.rs
└── rust_native_host_lib (Rust native rust code as library)
├── Cargo.toml
└── src
├── generated.rs
├── guest_imported_fns.rs
├── lib.rs
├── native_imports.rs
├── the_native_imports.rs
├── the_world_native.rs
└── the_world.rs
```
to build and run the application run the command

```shell
cargo run -p rust_app`
```

14 changes: 14 additions & 0 deletions crates/cpp/tests/native_strings/cpp_host/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
CXXFLAGS=-g -O0 -I../../../helper-types --std=c++17
WIT_BINDGEN=../../../../target/debug/wit-bindgen

all: the_world_native.o guest_imported_fns.o

the_world_native.o:
$(CXX) $(CXXFLAGS) -fPIE -o $@ -c the_world_native.cpp

guest_imported_fns.o:
$(CXX) $(CXXFLAGS) -fPIE -o $@ -c guest_imported_fns.cpp


clean:
-rm *.o
20 changes: 20 additions & 0 deletions crates/cpp/tests/native_strings/cpp_host/guest_imported_fns.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include "./the_world_cpp_native.h"
#include <iostream>

using namespace std;

void foo::foo::strings::A(std::string_view x)
{
std::cout << x << std::endl;
}
wit::string foo::foo::strings::B()
{
wit::string b = wit::string::from_view(std::string_view("hello B"));
return b;
}
wit::string foo::foo::strings::C(std::string_view a, std::string_view b)
{
std::cout << a << '|' << b << std::endl;
wit::string c = wit::string::from_view(std::string_view("hello C"));
return c;
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ fooX3AfooX2FstringsX23c(uint8_t *, size_t, uint8_t *, size_t);
extern "C" __attribute__((import_module("cabi_post_foo:foo/strings")))
__attribute__((import_name("c"))) void
cabi_post_fooX3AfooX2FstringsX23c(uint8_t *);
extern "C" void fooX3AfooX2FstringsX00a(uint8_t *arg0, size_t arg1) {
extern "C" void fooX3AfooX2FstringsX00a(uint8_t *arg0, size_t arg1) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

adding trailing whitespace?

auto len0 = arg1;

foo::foo::strings::A(std::string_view((char const *)(arg0), len0));
Expand Down Expand Up @@ -44,10 +44,10 @@ extern "C" void fooX3AfooX2FstringsX00c(uint8_t *arg0, size_t arg1,
*((size_t *)(arg4 + 8)) = len3;
*((uint8_t **)(arg4 + 0)) = ptr3;
}
void exports::foo::foo::strings::A(wit::string x) {
void exports::foo::foo::strings::A(wit::string x) {
auto const &vec0 = x;
auto ptr0 = vec0.data();
auto len0 = vec0.size();
auto len0 = vec0.size();
fooX3AfooX2FstringsX23a(ptr0, len0);
}
wit::guest_owned<std::string_view> exports::foo::foo::strings::B() {
Expand Down
35 changes: 35 additions & 0 deletions crates/cpp/tests/native_strings/guest/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
CXXFLAGS=-g -O0 -I../../../helper-types --std=c++17
WIT_BINDGEN=../../../../target/debug/wit-bindgen

all: libstrings.so

libstrings.so: the_world.pie.o guest.pie.o
$(CXX) $(CXXFLAGS) -shared -o $@ $^ -Wl,--version-script=guest.lds

%.pie.o: %.cpp
$(CXX) $(CXXFLAGS) -fPIE -o $@ -c $^

bindgen: wit/strings.wit
$(WIT_BINDGEN) cpp wit --wasm64 --format
cd cpp_host
$(WIT_BINDGEN) cpp wit --wasm64 --format --direct
cd -
cd rust/src ; ../../$(WIT_BINDGEN) rust ../../wit --wasm64

guest.wasm: the_world.cpp guest.cpp
/opt/wasi-sdk/bin/clang++ -o $@ $^ $(CXXFLAGS)

guest_release.wasm: the_world.cpp guest.cpp
/opt/wasi-sdk/bin/clang++ -o $@ $^ $(CXXFLAGS) -g0 -O3

clean:
-rm *.o libstrings.so app-strings

run:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fear these targets don't make much sense for the guest directory

LD_LIBRARY_PATH=. ./app-strings

valgrind:
LD_LIBRARY_PATH=. valgrind ./app-strings

w2c2_guest.c: guest_release.wasm
w2c2 $^ $@
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
#include "the_world_cpp.h"

void exports::foo::foo::strings::A(wit::string &&x) {
void exports::foo::foo::strings::A(wit::string &&x)
{
::foo::foo::strings::A(x.get_view());
}

wit::string exports::foo::foo::strings::B() {
wit::string exports::foo::foo::strings::B()
{
return ::foo::foo::strings::B();
}

wit::string exports::foo::foo::strings::C(wit::string &&x, wit::string &&b) {
wit::string exports::foo::foo::strings::C(wit::string &&x, wit::string &&b)
{
return ::foo::foo::strings::C(x.get_view(), b.get_view());
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ fooX3AfooX2FstringsX00b(uint8_t *);
extern "C" __attribute__((import_module("foo:foo/strings")))
__attribute__((import_name("c"))) void
fooX3AfooX2FstringsX00c(uint8_t *, size_t, uint8_t *, size_t, uint8_t *);
void foo::foo::strings::A(std::string_view x) {
void foo::foo::strings::A(std::string_view x) {
auto const &vec0 = x;
auto ptr0 = (uint8_t *)(vec0.data());
auto len0 = (size_t)(vec0.size());
Expand Down Expand Up @@ -63,9 +63,8 @@ wit::string foo::foo::strings::C(std::string_view a, std::string_view b) {
return wit::string((char const *)(*((uint8_t **)(ptr2 + 0))), len3);
}
extern "C" __attribute__((__export_name__("foo:foo/strings#a"))) void
fooX3AfooX2FstringsX23a(uint8_t *arg0, size_t arg1) {
auto len0 = arg1;

fooX3AfooX2FstringsX23a(uint8_t *arg0, size_t arg1) {
auto len0 = arg1;
exports::foo::foo::strings::A(wit::string((char const *)(arg0), len0));
}
extern "C" __attribute__((__export_name__("foo:foo/strings#b"))) uint8_t *
Expand Down
15 changes: 1 addition & 14 deletions crates/cpp/tests/native_strings/main.cpp
Original file line number Diff line number Diff line change
@@ -1,20 +1,7 @@

#include "the_world_cpp_native.h"
#include "./cpp_host/the_world_cpp_native.h"
#include <iostream>

void foo::foo::strings::A(std::string_view x) {
std::cout << x << std::endl;
}
wit::string foo::foo::strings::B() {
wit::string b = wit::string::from_view(std::string_view("hello B"));
return b;
}
wit::string foo::foo::strings::C(std::string_view a, std::string_view b) {
std::cout << a << '|' << b << std::endl;
wit::string c = wit::string::from_view(std::string_view("hello C"));
return c;
}

int main() {
wit::string a = wit::string::from_view(std::string_view("hello A"));
exports::foo::foo::strings::A(a);
Expand Down
7 changes: 7 additions & 0 deletions crates/cpp/tests/native_strings/rust-host/rust_app/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "rust_app"
version = "0.1.0"
edition = "2021"

[dependencies]
rust_native_host_lib = {path ="../rust_native_host_lib"}
14 changes: 14 additions & 0 deletions crates/cpp/tests/native_strings/rust-host/rust_app/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use rust_native_host_lib::the_world_native::exports::foo::foo::strings::{a, b, c};

fn main() {
a("hello a".into());
{
let b = b();
println!("{}", b);
}

let c1 = "hello C1";
let c2 = "hello C2";
let c = c(c1.into(), c2.into());
println!("{}",c);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "rust_native_host_lib"
version = "0.1.0"
edition.workspace = true

[dependencies]
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
use std::alloc::Layout;

use the_world::exports::foo::foo::strings::Guest;

mod the_world;

use crate::__export_foo_foo_strings_cabi;
use crate::the_world::exports::foo::foo::strings::Guest;
struct MyWorld;

impl Guest for MyWorld {
fn a(x: String,) {
the_world::foo::foo::strings::a(&x);
fn a(x: String) {
crate::the_world::foo::foo::strings::a(&x);
}

fn b() -> String {
the_world::foo::foo::strings::b()
crate::the_world::foo::foo::strings::b()
}

fn c(a: String,b: String,) -> String {
the_world::foo::foo::strings::c(&a, &b)
fn c(a: String, b: String) -> String {
crate::the_world::foo::foo::strings::c(&a, &b)
}
}

the_world::export!(MyWorld with_types_in the_world);
__export_foo_foo_strings_cabi!(MyWorld with_types_in crate::the_world::exports::foo::foo::strings);

// the crate wit-bindgen-rt doesn't work on native
#[no_mangle]
Expand All @@ -43,7 +41,7 @@ pub unsafe extern "C" fn cabi_realloc(
std::alloc::realloc(old_ptr, layout, new_len)
};
if ptr.is_null() {
unreachable!();
unreachable!();
}
return ptr;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
pub mod foo {
pub mod foo {
pub mod strings {

pub fn a(a: String) {
println!("{a}");
}
pub fn b() -> String {
let s = String::from("hello B");
s
}

pub fn c(a: String, b: String) -> String {
println!("guest imported: {} | {}", a, b);
let s = String::from("hello C");
s
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mod generated;
pub mod guest_imported_fns;
mod native_imports;
mod the_world;
pub mod the_world_native;
Loading