Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get multi.c working in the Wasm C API #1953

Merged
merged 4 commits into from
Dec 21, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions lib/c-api/src/wasm_c_api/externals/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub use table::*;
use wasmer::{Extern, Instance};

#[allow(non_camel_case_types)]
#[derive(Clone)]
pub struct wasm_extern_t {
// this is how we ensure the instance stays alive
pub(crate) instance: Option<Arc<Instance>>,
Expand Down
96 changes: 86 additions & 10 deletions lib/c-api/src/wasm_c_api/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,33 @@ macro_rules! wasm_declare_vec {
pub data: *mut [<wasm_ $name _t>],
}

impl Clone for [<wasm_ $name _vec_t>] {
fn clone(&self) -> Self {
if self.data.is_null() {
return Self {
size: self.size,
data: ::std::ptr::null_mut(),
};
}
let data =
unsafe {
let vec = Vec::from_raw_parts(self.data, self.size, self.size);
let mut vec_copy = vec.clone().into_boxed_slice();
let new_ptr = vec_copy.as_mut_ptr();

::std::mem::forget(vec);
::std::mem::forget(vec_copy);

new_ptr
};

Self {
size: self.size,
data,
}
}
}

impl<'a> From<Vec<[<wasm_ $name _t>]>> for [<wasm_ $name _vec_t>] {
fn from(mut vec: Vec<[<wasm_ $name _t>]>) -> Self {
vec.shrink_to_fit();
Expand Down Expand Up @@ -108,6 +135,15 @@ macro_rules! wasm_declare_vec {
::std::mem::forget(bytes);
}

#[doc = "Performs a deep copy of a vector of [`wasm_" $name "_t`]."]
#[no_mangle]
pub unsafe extern "C" fn [<wasm_ $name _vec_copy>](
out_ptr: &mut [<wasm_ $name _vec_t>],
in_ptr: & [<wasm _$name _vec_t>])
{
*out_ptr = in_ptr.clone();
}

#[doc = "Deletes a vector of [`wasm_" $name "_t`]."]
#[no_mangle]
pub unsafe extern "C" fn [<wasm_ $name _vec_delete>](ptr: Option<&mut [<wasm_ $name _vec_t>]>) {
Expand Down Expand Up @@ -138,6 +174,34 @@ macro_rules! wasm_declare_boxed_vec {
pub data: *mut *mut [<wasm_ $name _t>],
}

impl Clone for [<wasm_ $name _vec_t>] {
fn clone(&self) -> Self {
if self.data.is_null() {
return Self {
size: self.size,
data: ::std::ptr::null_mut(),
};
}
let data =
unsafe {
let data: *mut Option<Box<[<wasm_ $name _t>]>> = self.data as _;
let vec = Vec::from_raw_parts(data, self.size, self.size);
let mut vec_copy = vec.clone().into_boxed_slice();
let new_ptr = vec_copy.as_mut_ptr() as *mut *mut [<wasm_ $name _t>];

::std::mem::forget(vec);
::std::mem::forget(vec_copy);

new_ptr
};

Self {
size: self.size,
data,
}
}
}

impl<'a> From<Vec<Box<[<wasm_ $name _t>]>>> for [<wasm_ $name _vec_t>] {
fn from(other: Vec<Box<[<wasm_ $name _t>]>>) -> Self {
let boxed_slice: Box<[Box<[<wasm_ $name _t>]>]> = other.into_boxed_slice();
Expand Down Expand Up @@ -174,11 +238,11 @@ macro_rules! wasm_declare_boxed_vec {
for i in 0..length {
bytes.push(*init.add(i));
}
let pointer = bytes.as_mut_ptr();
debug_assert!(bytes.len() == bytes.capacity());
let mut boxed_vec = bytes.into_boxed_slice();
let pointer = boxed_vec.as_mut_ptr();
(*out).data = pointer;
(*out).size = length;
::std::mem::forget(bytes);
::std::mem::forget(boxed_vec);
}

#[doc = "Creates a new uninitialized vector of [`wasm_" $name "_t`]."]
Expand All @@ -191,15 +255,27 @@ macro_rules! wasm_declare_boxed_vec {
::std::mem::forget(bytes);
}

#[doc = "Performs a deep copy of a vector of [`wasm_" $name "_t`]."]
#[no_mangle]
pub unsafe extern "C" fn [<wasm_ $name _vec_copy>](
out_ptr: &mut [<wasm_ $name _vec_t>],
in_ptr: & [<wasm _$name _vec_t>])
{
*out_ptr = in_ptr.clone();
}


#[doc = "Deletes a vector of [`wasm_" $name "_t`]."]
#[no_mangle]
pub unsafe extern "C" fn [<wasm_ $name _vec_delete>](ptr: *mut [<wasm_ $name _vec_t>]) {
let vec = &mut *ptr;
if !vec.data.is_null() {
let data: Vec<*mut [<wasm_ $name _t>]> = Vec::from_raw_parts(vec.data, vec.size, vec.size);
let _data: Vec<Box<[<wasm_ $name _t>]>> = ::std::mem::transmute(data);
vec.data = ::std::ptr::null_mut();
vec.size = 0;
pub unsafe extern "C" fn [<wasm_ $name _vec_delete>](ptr: Option<&mut[<wasm_ $name _vec_t>]>) {
if let Some(vec) = ptr {
if !vec.data.is_null() {
let ptr: *mut Option<Box<[<wasm_ $name _t>]>> = vec.data as _;
let data: Vec<Option<Box<[<wasm_ $name _t>]>>> = Vec::from_raw_parts(ptr, vec.size, vec.size);

vec.data = ::std::ptr::null_mut();
vec.size = 0;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This conflicts with #1949.

}
}
}
Expand Down
1 change: 1 addition & 0 deletions lib/c-api/src/wasm_c_api/types/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use super::{wasm_externtype_t, wasm_name_t};
use wasmer::ExportType;

#[allow(non_camel_case_types)]
#[derive(Clone)]
pub struct wasm_exporttype_t {
name: Box<wasm_name_t>,
extern_type: Box<wasm_externtype_t>,
Expand Down
10 changes: 4 additions & 6 deletions lib/c-api/src/wasm_c_api/types/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ impl Clone for WasmFunctionType {
}

#[allow(non_camel_case_types)]
#[derive(Debug)]
#[derive(Debug, Clone)]
#[repr(transparent)]
pub struct wasm_functype_t {
pub(crate) extern_type: wasm_externtype_t,
Expand Down Expand Up @@ -111,8 +111,8 @@ pub unsafe extern "C" fn wasm_functype_new(
.map(|val| val.as_ref().into())
.collect::<Vec<_>>();

wasm_valtype_vec_delete(Box::into_raw(params));
wasm_valtype_vec_delete(Box::into_raw(results));
wasm_valtype_vec_delete(Some(&mut *Box::into_raw(params)));
wasm_valtype_vec_delete(Some(&mut *Box::into_raw(results)));

Some(Box::new(wasm_functype_t::new(FunctionType::new(
params_as_valtype,
Expand All @@ -129,9 +129,7 @@ pub unsafe extern "C" fn wasm_functype_copy(
) -> Option<Box<wasm_functype_t>> {
let function_type = function_type?;

Some(Box::new(wasm_functype_t::new(
function_type.inner().function_type.clone(),
)))
Some(Box::new(function_type.clone()))
}

#[no_mangle]
Expand Down
2 changes: 1 addition & 1 deletion lib/c-api/src/wasm_c_api/types/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ impl WasmGlobalType {
}

#[allow(non_camel_case_types)]
#[derive(Debug)]
#[derive(Debug, Clone)]
#[repr(transparent)]
pub struct wasm_globaltype_t {
pub(crate) extern_type: wasm_externtype_t,
Expand Down
1 change: 1 addition & 0 deletions lib/c-api/src/wasm_c_api/types/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use super::{wasm_externtype_t, wasm_name_t};
use wasmer::ImportType;

#[allow(non_camel_case_types)]
#[derive(Clone)]
pub struct wasm_importtype_t {
module: Box<wasm_name_t>,
name: Box<wasm_name_t>,
Expand Down
2 changes: 1 addition & 1 deletion lib/c-api/src/wasm_c_api/types/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ impl WasmMemoryType {
}

#[allow(non_camel_case_types)]
#[derive(Debug)]
#[derive(Debug, Clone)]
#[repr(transparent)]
pub struct wasm_memorytype_t {
pub(crate) extern_type: wasm_externtype_t,
Expand Down
2 changes: 1 addition & 1 deletion lib/c-api/src/wasm_c_api/types/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ impl WasmTableType {
}

#[allow(non_camel_case_types)]
#[derive(Debug)]
#[derive(Debug, Clone)]
#[repr(transparent)]
pub struct wasm_tabletype_t {
pub(crate) extern_type: wasm_externtype_t,
Expand Down
33 changes: 33 additions & 0 deletions lib/c-api/src/wasm_c_api/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,39 @@ pub struct wasm_val_t {
pub of: wasm_val_inner,
}

impl std::fmt::Debug for wasm_val_t {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let mut ds = f.debug_struct("wasm_val_t");
ds.field("kind", &self.kind);

match self.kind.try_into() {
Ok(wasm_valkind_enum::WASM_I32) => {
ds.field("i32", &unsafe { self.of.int32_t });
}
Ok(wasm_valkind_enum::WASM_I64) => {
ds.field("i64", &unsafe { self.of.int64_t });
}
Ok(wasm_valkind_enum::WASM_F32) => {
ds.field("f32", &unsafe { self.of.float32_t });
}
Ok(wasm_valkind_enum::WASM_F64) => {
ds.field("f64", &unsafe { self.of.float64_t });
}
Ok(wasm_valkind_enum::WASM_ANYREF) => {
ds.field("anyref", &unsafe { self.of.wref });
}

Ok(wasm_valkind_enum::WASM_FUNCREF) => {
ds.field("funcref", &unsafe { self.of.wref });
}
Err(_) => {
ds.field("value", &"Invalid value type");
}
}
ds.finish()
}
}

wasm_declare_vec!(val);

impl Clone for wasm_val_t {
Expand Down
4 changes: 2 additions & 2 deletions lib/c-api/tests/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ CAPI_WASMER_TESTS = \
CAPI_BASE_TESTS = \
wasm-c-api/example/callback wasm-c-api/example/global wasm-c-api/example/hello \
wasm-c-api/example/memory wasm-c-api/example/reflect wasm-c-api/example/serialize \
wasm-c-api/example/start wasm-c-api/example/trap
wasm-c-api/example/start wasm-c-api/example/trap wasm-c-api/example/multi

CAPI_BASE_TESTS_NOT_WORKING = \
wasm-c-api/example/finalize wasm-c-api/example/hostref wasm-c-api/example/multi \
wasm-c-api/example/finalize wasm-c-api/example/hostref \
wasm-c-api/example/table wasm-c-api/example/threads

DEPRECATED_TESTS = \
Expand Down
16 changes: 15 additions & 1 deletion lib/c-api/tests/wasm-c-api/example/multi.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@

#define own

int wasmer_last_error_length(void);
void wasmer_last_error_message(char*, int);

// Use the last_error API to retrieve error messages
void print_wasmer_error()
{
int error_len = wasmer_last_error_length();
printf("Error len: `%d`\n", error_len);
char *error_str = malloc(error_len);
wasmer_last_error_message(error_str, error_len);
printf("Error str: `%s`\n", error_str);
}

jubianchi marked this conversation as resolved.
Show resolved Hide resolved
// A function to be called from Wasm code.
own wasm_trap_t* callback(
const wasm_val_vec_t* args, wasm_val_vec_t* results
Expand Down Expand Up @@ -121,7 +134,7 @@ int main(int argc, const char* argv[]) {
// Call.
printf("Calling export...\n");
wasm_val_t vals[4] = {
WASM_I32_VAL(1), WASM_I32_VAL(2), WASM_I32_VAL(3), WASM_I32_VAL(4)
WASM_I32_VAL(1), WASM_I64_VAL(2), WASM_I64_VAL(3), WASM_I32_VAL(4)
Copy link
Member

Choose a reason for hiding this comment

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

Is this intended? Did the code was updated in the wasm-c-api side?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I linked to the PR on the Wasm C API above

};
wasm_val_t res[4] = {
WASM_INIT_VAL, WASM_INIT_VAL, WASM_INIT_VAL, WASM_INIT_VAL
Expand All @@ -130,6 +143,7 @@ int main(int argc, const char* argv[]) {
wasm_val_vec_t results = WASM_ARRAY_VEC(res);
if (wasm_func_call(run_func, &args, &results)) {
printf("> Error calling function!\n");
print_wasmer_error();
return 1;
}

Expand Down