diff --git a/.gitmodules b/.gitmodules index 6cd1abf41..a694cec89 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "crates/mun_abi/c"] path = crates/mun_abi/c url = ../../mun-lang/abi-c +[submodule "crates/mun_runtime_capi/c"] + path = crates/mun_runtime_capi/c + url = ../../mun-lang/runtime-c.git diff --git a/crates/mun_runtime_capi/Cargo.toml b/crates/mun_runtime_capi/Cargo.toml new file mode 100644 index 000000000..ea17c1398 --- /dev/null +++ b/crates/mun_runtime_capi/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "mun_runtime_capi" +version = "0.1.0" +authors = ["Wodann "] +edition = "2018" + +[dependencies] +mun_abi = { path = "../mun_abi" } +mun_runtime = { path = "../mun_runtime" } + +[build-dependencies] +cbindgen = "0.9.1" diff --git a/crates/mun_runtime_capi/build.rs b/crates/mun_runtime_capi/build.rs new file mode 100644 index 000000000..9f6b92e6d --- /dev/null +++ b/crates/mun_runtime_capi/build.rs @@ -0,0 +1,11 @@ +use std::env; + +use cbindgen; + +fn main() { + let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + + cbindgen::generate(crate_dir) + .expect("Unable to generate Mun Runtime bindings.") + .write_to_file("c/include/mun_runtime.h"); +} diff --git a/crates/mun_runtime_capi/c b/crates/mun_runtime_capi/c new file mode 160000 index 000000000..f9d3d6c3b --- /dev/null +++ b/crates/mun_runtime_capi/c @@ -0,0 +1 @@ +Subproject commit f9d3d6c3b9c8bd0cc38279b85dfcc3debdc34b07 diff --git a/crates/mun_runtime_capi/cbindgen.toml b/crates/mun_runtime_capi/cbindgen.toml new file mode 100644 index 000000000..3e4409a8e --- /dev/null +++ b/crates/mun_runtime_capi/cbindgen.toml @@ -0,0 +1,17 @@ +language = "C" +cpp_compat = true + +include_guard = "MUN_RUNTIME_BINDINGS_H_" +include_version = true +sys_includes = ["stdbool.h", "stdint.h"] +no_includes = true + +line_length = 100 +tab_width = 4 + +[export] +prefix = "Mun" + +[parse] +parse_deps = true +include = ["mun_abi"] diff --git a/crates/mun_runtime_capi/src/lib.rs b/crates/mun_runtime_capi/src/lib.rs new file mode 100644 index 000000000..5c4b06dab --- /dev/null +++ b/crates/mun_runtime_capi/src/lib.rs @@ -0,0 +1,94 @@ +use mun_abi::FunctionInfo; +use mun_runtime::{MunRuntime, RuntimeBuilder}; +use std::ffi::{c_void, CStr}; +use std::os::raw::c_char; + +#[repr(C)] +pub struct RuntimeHandle(*mut c_void); + +#[no_mangle] +pub extern "C" fn create_runtime(library_path: *const c_char, handle: *mut RuntimeHandle) -> u64 /* error */ +{ + if library_path.is_null() { + return 1; + } + + let library_path = match unsafe { CStr::from_ptr(library_path) }.to_str() { + Ok(path) => path, + Err(_) => return 2, + }; + + let handle = match unsafe { handle.as_mut() } { + Some(handle) => handle, + None => return 3, + }; + + let runtime = match RuntimeBuilder::new(library_path).spawn() { + Ok(runtime) => runtime, + Err(_) => return 4, + }; + + handle.0 = Box::into_raw(Box::new(runtime)) as *mut _; + 0 +} + +#[no_mangle] +pub extern "C" fn destroy_runtime(handle: RuntimeHandle) { + if !handle.0.is_null() { + let _runtime = unsafe { Box::from_raw(handle.0) }; + } +} + +#[no_mangle] +pub extern "C" fn runtime_get_function_info( + handle: RuntimeHandle, + fn_name: *const c_char, + has_fn_info: *mut bool, + fn_info: *mut FunctionInfo, +) -> u64 /* error */ { + let runtime = match unsafe { (handle.0 as *mut MunRuntime).as_ref() } { + Some(runtime) => runtime, + None => return 1, + }; + + let fn_name = match unsafe { CStr::from_ptr(fn_name) }.to_str() { + Ok(name) => name, + Err(_) => return 2, + }; + + let has_fn_info = match unsafe { has_fn_info.as_mut() } { + Some(has_info) => has_info, + None => return 3, + }; + + let fn_info = match unsafe { fn_info.as_mut() } { + Some(info) => info, + None => return 4, + }; + + match runtime.get_function_info(fn_name) { + Some(info) => { + *has_fn_info = true; + *fn_info = info.clone(); + } + None => *has_fn_info = false, + } + + 0 +} + +#[no_mangle] +pub extern "C" fn runtime_update(handle: RuntimeHandle, updated: *mut bool) -> u64 /* error */ { + let runtime = match unsafe { (handle.0 as *mut MunRuntime).as_mut() } { + Some(runtime) => runtime, + None => return 1, + }; + + let updated = match unsafe { updated.as_mut() } { + Some(updated) => updated, + None => return 2, + }; + + *updated = runtime.update(); + 0 +}