Use higher level types in C API where possible

This commit is contained in:
Mark McCaskey
2020-05-11 13:18:07 -07:00
parent 01672995f9
commit 66b6dc2615
9 changed files with 128 additions and 103 deletions

View File

@@ -1,12 +1,11 @@
//! Read runtime errors.
use libc::{c_char, c_int};
use std::{
cell::RefCell,
error::Error,
fmt::{self, Display, Formatter},
ptr, slice,
};
use std::cell::RefCell;
use std::error::Error;
use std::fmt::{self, Display, Formatter};
use std::ptr::{self, NonNull};
use std::slice;
thread_local! {
static LAST_ERROR: RefCell<Option<Box<dyn Error>>> = RefCell::new(None);
@@ -66,11 +65,16 @@ pub extern "C" fn wasmer_last_error_length() -> c_int {
/// }
/// ```
#[no_mangle]
pub unsafe extern "C" fn wasmer_last_error_message(buffer: *mut c_char, length: c_int) -> c_int {
if buffer.is_null() {
pub unsafe extern "C" fn wasmer_last_error_message(
buffer: Option<NonNull<c_char>>,
length: c_int,
) -> c_int {
let buffer = if let Some(buffer_inner) = buffer {
buffer_inner
} else {
// buffer pointer is null
return -1;
}
};
let error_message = match take_last_error() {
Some(err) => err.to_string(),
@@ -84,7 +88,7 @@ pub unsafe extern "C" fn wasmer_last_error_message(buffer: *mut c_char, length:
return -1;
}
let buffer = slice::from_raw_parts_mut(buffer as *mut u8, length);
let buffer = slice::from_raw_parts_mut(buffer.cast::<u8>().as_ptr(), length);
ptr::copy_nonoverlapping(
error_message.as_ptr(),

View File

@@ -23,7 +23,7 @@ pub(crate) struct NamedExport {
pub(crate) export_type: ExportType,
/// The instance that holds the export.
pub(crate) instance: *mut Instance,
pub(crate) instance: NonNull<Instance>,
}
/// Opaque pointer to `ImportType`.
@@ -400,7 +400,7 @@ pub unsafe extern "C" fn wasmer_export_to_memory(
memory: *mut *mut wasmer_memory_t,
) -> wasmer_result_t {
let named_export = &*(export as *const NamedExport);
let instance = &*named_export.instance;
let instance = named_export.instance.as_ref();
if let Ok(exported_memory) = instance
.exports
@@ -476,7 +476,7 @@ pub unsafe extern "C" fn wasmer_export_func_call(
let results: &mut [wasmer_value_t] = slice::from_raw_parts_mut(results, results_len as usize);
let instance = &*named_export.instance;
let instance = named_export.instance.as_ref();
let f: &Function = match instance.exports.get(&named_export.export_type.name()) {
Ok(f) => f,
Err(err) => {

View File

@@ -1,6 +1,8 @@
//! Create, set, get and destroy global variables of an instance.
use crate::error::update_last_error;
use crate::value::{wasmer_value_t, wasmer_value_tag};
use std::ptr::NonNull;
use wasmer::Global;
#[repr(C)]
@@ -17,10 +19,7 @@ pub struct wasmer_global_t;
/// Creates a new Global and returns a pointer to it.
/// The caller owns the object and should call `wasmer_global_destroy` to free it.
#[no_mangle]
pub unsafe extern "C" fn wasmer_global_new(
value: wasmer_value_t,
mutable: bool,
) -> *mut wasmer_global_t {
pub extern "C" fn wasmer_global_new(value: wasmer_value_t, mutable: bool) -> *mut wasmer_global_t {
let store = crate::get_global_store();
let global = if mutable {
Global::new_mut(store, value.into())
@@ -33,8 +32,8 @@ pub unsafe extern "C" fn wasmer_global_new(
/// Gets the value stored by the given Global
#[allow(clippy::cast_ptr_alignment)]
#[no_mangle]
pub extern "C" fn wasmer_global_get(global: *mut wasmer_global_t) -> wasmer_value_t {
let global = unsafe { &*(global as *mut Global) };
pub unsafe extern "C" fn wasmer_global_get(global: *mut wasmer_global_t) -> wasmer_value_t {
let global = &*(global as *mut Global);
let value: wasmer_value_t = global.get().into();
value
}
@@ -42,18 +41,22 @@ pub extern "C" fn wasmer_global_get(global: *mut wasmer_global_t) -> wasmer_valu
/// Sets the value stored by the given Global
#[allow(clippy::cast_ptr_alignment)]
#[no_mangle]
pub extern "C" fn wasmer_global_set(global: *mut wasmer_global_t, value: wasmer_value_t) {
let global = unsafe { &*(global as *mut Global) };
global.set(value.into());
pub unsafe extern "C" fn wasmer_global_set(global: *mut wasmer_global_t, value: wasmer_value_t) {
let global = &*(global as *mut Global);
if let Err(err) = global.set(value.into()) {
update_last_error(err);
// can't return an error without breaking the API, probaly a safe change
// return wasmer_result_t::WASMER_ERROR;
}
}
/// Returns a descriptor (type, mutability) of the given Global
#[allow(clippy::cast_ptr_alignment)]
#[no_mangle]
pub extern "C" fn wasmer_global_get_descriptor(
pub unsafe extern "C" fn wasmer_global_get_descriptor(
global: *mut wasmer_global_t,
) -> wasmer_global_descriptor_t {
let global = unsafe { &*(global as *mut Global) };
let global = &*(global as *mut Global);
let descriptor = global.ty();
wasmer_global_descriptor_t {
mutable: descriptor.mutability.into(),
@@ -64,8 +67,8 @@ pub extern "C" fn wasmer_global_get_descriptor(
/// Frees memory for the given Global
#[allow(clippy::cast_ptr_alignment)]
#[no_mangle]
pub extern "C" fn wasmer_global_destroy(global: *mut wasmer_global_t) {
if !global.is_null() {
unsafe { Box::from_raw(global as *mut Global) };
pub unsafe extern "C" fn wasmer_global_destroy(global: Option<NonNull<wasmer_global_t>>) {
if let Some(global_inner) = global {
Box::from_raw(global_inner.cast::<Global>().as_ptr());
}
}

View File

@@ -10,11 +10,11 @@ use crate::{
wasmer_byte_array, wasmer_result_t,
};
use libc::c_uint;
use std::ptr::NonNull;
use std::{
//convert::TryFrom,
ffi::c_void,
os::raw::c_char,
ptr,
slice,
//sync::Arc,
};
@@ -58,10 +58,11 @@ pub struct wasmer_import_object_iter_t;
/// See also `wasmer_import_object_append`
#[allow(clippy::cast_ptr_alignment)]
#[no_mangle]
pub unsafe extern "C" fn wasmer_import_object_new() -> *mut wasmer_import_object_t {
pub extern "C" fn wasmer_import_object_new() -> NonNull<wasmer_import_object_t> {
let import_object = Box::new(ImportObject::new());
Box::into_raw(import_object) as *mut wasmer_import_object_t
// TODO: use `Box::into_raw_non_null` when it becomes stable
unsafe { NonNull::new_unchecked(Box::into_raw(import_object) as *mut wasmer_import_object_t) }
}
#[cfg(feature = "wasi")]
@@ -319,15 +320,17 @@ pub unsafe extern "C" fn wasmer_import_object_iter_next(
/// not return any new data
#[no_mangle]
pub unsafe extern "C" fn wasmer_import_object_iter_at_end(
import_object_iter: *mut wasmer_import_object_iter_t,
import_object_iter: Option<NonNull<wasmer_import_object_iter_t>>,
) -> bool {
if import_object_iter.is_null() {
let mut import_object_iter = if let Some(ioi) = import_object_iter {
ioi.cast::<WasmerImportObjectIterator>()
} else {
update_last_error(CApiError {
msg: "import_object_iter must not be null".to_owned(),
});
return true;
}
let iter = &mut *(import_object_iter as *mut WasmerImportObjectIterator);
};
let iter = import_object_iter.as_mut();
iter.0.peek().is_none()
}
@@ -335,10 +338,10 @@ pub unsafe extern "C" fn wasmer_import_object_iter_at_end(
/// Frees the memory allocated by `wasmer_import_object_iterate_functions`
#[no_mangle]
pub unsafe extern "C" fn wasmer_import_object_iter_destroy(
import_object_iter: *mut wasmer_import_object_iter_t,
import_object_iter: Option<NonNull<wasmer_import_object_iter_t>>,
) {
if !import_object_iter.is_null() {
let _ = Box::from_raw(import_object_iter as *mut WasmerImportObjectIterator);
if let Some(ioi) = import_object_iter {
let _ = Box::from_raw(ioi.cast::<WasmerImportObjectIterator>().as_ptr());
}
}
@@ -348,13 +351,16 @@ pub unsafe extern "C" fn wasmer_import_object_iter_destroy(
/// it only frees memory allocated while querying a `wasmer_import_object_t`.
#[no_mangle]
pub unsafe extern "C" fn wasmer_import_object_imports_destroy(
imports: *mut wasmer_import_t,
imports: Option<NonNull<wasmer_import_t>>,
imports_len: u32,
) {
if imports.is_null() {
let imports = if let Some(imp) = imports {
imp
} else {
return;
}
let imports: &[wasmer_import_t] = &*slice::from_raw_parts_mut(imports, imports_len as usize);
};
let imports: &[wasmer_import_t] =
&*slice::from_raw_parts_mut(imports.as_ptr(), imports_len as usize);
for import in imports {
let _namespace: Vec<u8> = Vec::from_raw_parts(
import.module_name.bytes as *mut u8,
@@ -459,13 +465,14 @@ pub unsafe extern "C" fn wasmer_import_object_extend(
#[allow(clippy::cast_ptr_alignment)]
#[no_mangle]
pub unsafe extern "C" fn wasmer_import_descriptors(
module: *const wasmer_module_t,
module: Option<&wasmer_module_t>,
import_descriptors: *mut *mut wasmer_import_descriptors_t,
) {
if module.is_null() {
let module = if let Some(module) = module {
&*(module as *const wasmer_module_t as *const Module)
} else {
return;
}
let module = &*(module as *const Module);
};
let descriptors = module.imports().collect::<Vec<ImportType>>();
let named_import_descriptors: Box<NamedImportDescriptors> =
@@ -480,10 +487,10 @@ pub struct NamedImportDescriptors(Vec<ImportType>);
#[allow(clippy::cast_ptr_alignment)]
#[no_mangle]
pub extern "C" fn wasmer_import_descriptors_destroy(
import_descriptors: *mut wasmer_import_descriptors_t,
import_descriptors: Option<NonNull<wasmer_import_descriptors_t>>,
) {
if !import_descriptors.is_null() {
unsafe { Box::from_raw(import_descriptors as *mut NamedImportDescriptors) };
if let Some(id) = import_descriptors {
unsafe { Box::from_raw(id.cast::<NamedImportDescriptors>().as_ptr()) };
}
}
@@ -491,27 +498,29 @@ pub extern "C" fn wasmer_import_descriptors_destroy(
#[allow(clippy::cast_ptr_alignment)]
#[no_mangle]
pub unsafe extern "C" fn wasmer_import_descriptors_len(
exports: *mut wasmer_import_descriptors_t,
exports: Option<NonNull<wasmer_import_descriptors_t>>,
) -> c_uint {
if exports.is_null() {
let exports = if let Some(exports) = exports {
exports.cast::<NamedImportDescriptors>()
} else {
return 0;
}
(*(exports as *mut NamedImportDescriptors)).0.len() as c_uint
};
exports.as_ref().0.len() as c_uint
}
/// Gets import descriptor by index
#[allow(clippy::cast_ptr_alignment)]
#[no_mangle]
pub unsafe extern "C" fn wasmer_import_descriptors_get(
import_descriptors: *mut wasmer_import_descriptors_t,
import_descriptors: Option<NonNull<wasmer_import_descriptors_t>>,
idx: c_uint,
) -> *mut wasmer_import_descriptor_t {
if import_descriptors.is_null() {
return ptr::null_mut();
}
let named_import_descriptors = &mut *(import_descriptors as *mut NamedImportDescriptors);
&mut (*named_import_descriptors).0[idx as usize] as *mut ImportType
as *mut wasmer_import_descriptor_t
) -> Option<NonNull<wasmer_import_descriptor_t>> {
let mut nid = import_descriptors?.cast::<NamedImportDescriptors>();
let named_import_descriptors = nid.as_mut();
Some(
NonNull::from(&mut named_import_descriptors.0[idx as usize])
.cast::<wasmer_import_descriptor_t>(),
)
}
/// Gets name for the import descriptor
@@ -754,16 +763,18 @@ pub unsafe extern "C" fn wasmer_import_func_returns_arity(
/// Frees memory for the given Func
#[allow(clippy::cast_ptr_alignment)]
#[no_mangle]
pub extern "C" fn wasmer_import_func_destroy(func: *mut wasmer_import_func_t) {
if !func.is_null() {
unsafe { Box::from_raw(func as *mut Function) };
pub unsafe extern "C" fn wasmer_import_func_destroy(func: Option<NonNull<wasmer_import_func_t>>) {
if let Some(func) = func {
Box::from_raw(func.cast::<Function>().as_ptr());
}
}
/// Frees memory of the given ImportObject
#[no_mangle]
pub extern "C" fn wasmer_import_object_destroy(import_object: *mut wasmer_import_object_t) {
if !import_object.is_null() {
unsafe { Box::from_raw(import_object as *mut ImportObject) };
pub unsafe extern "C" fn wasmer_import_object_destroy(
import_object: Option<NonNull<wasmer_import_object_t>>,
) {
if let Some(import_object) = import_object {
Box::from_raw(import_object.cast::<ImportObject>().as_ptr());
}
}

View File

@@ -11,7 +11,7 @@ use crate::{
use libc::{c_char, c_int, c_void};
use std::collections::HashMap;
use std::ffi::CStr;
use std::ptr;
use std::ptr::NonNull;
use std::slice;
use wasmer::{
Exports, Extern, Function, Global, ImportObject, Instance, Memory, Module, Table, Val,
@@ -99,17 +99,19 @@ pub struct wasmer_instance_context_t;
#[no_mangle]
pub unsafe extern "C" fn wasmer_instantiate(
instance: *mut *mut wasmer_instance_t,
wasm_bytes: *mut u8,
wasm_bytes: Option<NonNull<u8>>,
wasm_bytes_len: u32,
imports: *mut wasmer_import_t,
imports_len: c_int,
) -> wasmer_result_t {
if wasm_bytes.is_null() {
let wasm_bytes = if let Some(wasm_bytes_inner) = wasm_bytes {
wasm_bytes_inner
} else {
update_last_error(CApiError {
msg: "wasm bytes ptr is null".to_string(),
});
return wasmer_result_t::WASMER_ERROR;
}
};
let imports: &[wasmer_import_t] = slice::from_raw_parts(imports, imports_len as usize);
let mut import_object = ImportObject::new();
let mut namespaces = HashMap::new();
@@ -166,7 +168,7 @@ pub unsafe extern "C" fn wasmer_instantiate(
import_object.register(module_name, namespace);
}
let bytes: &[u8] = slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize);
let bytes: &[u8] = slice::from_raw_parts_mut(wasm_bytes.as_ptr(), wasm_bytes_len as usize);
let store = crate::get_global_store();
let module_result = Module::from_binary(store, bytes);
@@ -206,15 +208,11 @@ pub unsafe extern "C" fn wasmer_instantiate(
#[allow(clippy::cast_ptr_alignment)]
#[no_mangle]
pub extern "C" fn wasmer_instance_context_get(
instance: *mut wasmer_instance_t,
) -> *const wasmer_instance_context_t {
if instance.is_null() {
return ptr::null() as _;
}
instance: Option<NonNull<wasmer_instance_t>>,
) -> Option<NonNull<wasmer_instance_context_t>> {
unimplemented!("wasmer_instance_context_get: API changed")
/*
let instance = unsafe { &*(instance as *const Instance) };
let instance = instance?.as_ref();
let context: *const Ctx = instance.context() as *const _;
context as *const wasmer_instance_context_t
@@ -403,20 +401,24 @@ pub unsafe extern "C" fn wasmer_instance_call(
#[allow(clippy::cast_ptr_alignment)]
#[no_mangle]
pub unsafe extern "C" fn wasmer_instance_exports(
instance: *mut wasmer_instance_t,
instance: Option<NonNull<wasmer_instance_t>>,
exports: *mut *mut wasmer_exports_t,
) {
if instance.is_null() {
let instance = if let Some(instance) = instance {
instance.cast::<Instance>()
} else {
return;
}
};
let instance_ref = &mut *(instance as *mut Instance);
let mut exports_vec: Vec<NamedExport> = instance_ref
let mut instance_ref_copy = instance.clone();
let instance_ref = instance_ref_copy.as_mut();
let exports_vec: Vec<NamedExport> = instance_ref
.module()
.exports()
.map(|export_type| NamedExport {
export_type,
instance: instance as *mut Instance,
instance,
})
.collect();
@@ -551,8 +553,8 @@ pub extern "C" fn wasmer_instance_context_data_get(
/// ```
#[allow(clippy::cast_ptr_alignment)]
#[no_mangle]
pub extern "C" fn wasmer_instance_destroy(instance: *mut wasmer_instance_t) {
if !instance.is_null() {
unsafe { Box::from_raw(instance as *mut Instance) };
pub extern "C" fn wasmer_instance_destroy(instance: Option<NonNull<wasmer_instance_t>>) {
if let Some(instance_inner) = instance {
unsafe { Box::from_raw(instance_inner.cast::<Instance>().as_ptr()) };
}
}

View File

@@ -196,7 +196,7 @@ pub unsafe extern "C" fn wasmer_module_serialize(
let module = &*(module as *const Module);
match module.serialize() {
Ok(mut serialized_module) => {
Ok(serialized_module) => {
let boxed_slice = serialized_module.into_boxed_slice();
*serialized_module_out = Box::into_raw(Box::new(boxed_slice)) as _;
@@ -267,16 +267,17 @@ pub unsafe extern "C" fn wasmer_serialized_module_from_bytes(
#[no_mangle]
pub unsafe extern "C" fn wasmer_module_deserialize(
module: *mut *mut wasmer_module_t,
serialized_module: *const wasmer_serialized_module_t,
serialized_module: Option<&wasmer_serialized_module_t>,
) -> wasmer_result_t {
if serialized_module.is_null() {
let serialized_module: &[u8] = if let Some(sm) = serialized_module {
&*(sm as *const wasmer_serialized_module_t as *const &[u8])
} else {
update_last_error(CApiError {
msg: "`serialized_module` pointer is null".to_string(),
});
return wasmer_result_t::WASMER_ERROR;
}
};
let serialized_module: &[u8] = &*(serialized_module as *const &[u8]);
let store = crate::get_global_store();
match Module::deserialize(store, serialized_module) {

View File

@@ -1,6 +1,7 @@
//! Create, grow, destroy tables of an instance.
use crate::{error::update_last_error, wasmer_limits_t, wasmer_result_t};
use std::ptr::NonNull;
use wasmer::{AnyRef, Table, TableType, Val, ValType};
#[repr(C)]
@@ -15,8 +16,8 @@ fn get_default_table_value(table_type: ValType) -> Val {
ValType::F32 => Val::F32(0.),
ValType::F64 => Val::F64(0.),
ValType::V128 => Val::V128(0),
ValType::AnyRef => Val::AnyRef(AnyRef::null()), // todo!("Figure out what the default AnyRef value is"),
ValType::FuncRef => Val::AnyRef(AnyRef::null()), //todo!("Figure out what the default FuncRef value is"),
ValType::AnyRef => Val::AnyRef(AnyRef::null()),
ValType::FuncRef => Val::AnyRef(AnyRef::null()),
}
}
@@ -65,8 +66,11 @@ pub unsafe extern "C" fn wasmer_table_new(
/// and `wasmer_last_error_message` to get an error message.
#[allow(clippy::cast_ptr_alignment)]
#[no_mangle]
pub extern "C" fn wasmer_table_grow(table: *mut wasmer_table_t, delta: u32) -> wasmer_result_t {
let table = unsafe { &*(table as *mut Table) };
pub unsafe extern "C" fn wasmer_table_grow(
table: *mut wasmer_table_t,
delta: u32,
) -> wasmer_result_t {
let table = &*(table as *mut Table);
let table_type = table.ty().ty;
let table_default_value = get_default_table_value(table_type);
let delta_result = table.grow(delta, table_default_value);
@@ -82,16 +86,16 @@ pub extern "C" fn wasmer_table_grow(table: *mut wasmer_table_t, delta: u32) -> w
/// Returns the current length of the given Table
#[allow(clippy::cast_ptr_alignment)]
#[no_mangle]
pub extern "C" fn wasmer_table_length(table: *mut wasmer_table_t) -> u32 {
let table = unsafe { &*(table as *mut Table) };
pub unsafe extern "C" fn wasmer_table_length(table: *mut wasmer_table_t) -> u32 {
let table = &*(table as *mut Table);
table.size()
}
/// Frees memory for the given Table
#[allow(clippy::cast_ptr_alignment)]
#[no_mangle]
pub extern "C" fn wasmer_table_destroy(table: *mut wasmer_table_t) {
if !table.is_null() {
unsafe { Box::from_raw(table as *mut Table) };
pub unsafe extern "C" fn wasmer_table_destroy(table: Option<NonNull<wasmer_table_t>>) {
if let Some(table_inner) = table {
Box::from_raw(table_inner.cast::<Table>().as_ptr());
}
}

View File

@@ -942,7 +942,7 @@ void wasmer_instance_context_data_set(wasmer_instance_t *instance,
*
* It is often useful with `wasmer_instance_context_data_set()`.
*/
const wasmer_instance_context_t *wasmer_instance_context_get(wasmer_instance_t *instance);
wasmer_instance_context_t *wasmer_instance_context_get(wasmer_instance_t *instance);
/**
* Gets the `memory_idx`th memory of the instance.

View File

@@ -751,7 +751,7 @@ void wasmer_instance_context_data_set(wasmer_instance_t *instance,
/// ```
///
/// It is often useful with `wasmer_instance_context_data_set()`.
const wasmer_instance_context_t *wasmer_instance_context_get(wasmer_instance_t *instance);
wasmer_instance_context_t *wasmer_instance_context_get(wasmer_instance_t *instance);
/// Gets the `memory_idx`th memory of the instance.
///