use crate::binds::{mono_jit_cleanup, mono_jit_exec, mono_jit_init, mono_jit_init_version};
use crate::domain::Domain;
use std::ffi::CString;
use std::sync::{LazyLock, Mutex};
static MAIN_DOMAIN: Mutex<Option<Domain>> = Mutex::new(None);
thread_local! {
static THREAD_REGISTERED:LazyLock<()> = LazyLock::new(||{
MAIN_DOMAIN.lock().unwrap().expect("Attempted to register a domain thread before the JIT is initialized").attach_thread();
});
}
pub(crate) fn esnure_thread_registered() {
THREAD_REGISTERED.with(|lock| {
let _ = *lock;
})
}
pub fn init(name: &str, version: Option<&str>) -> Domain {
let mut domain = MAIN_DOMAIN.lock().unwrap();
assert!(
domain.is_none(),
"Mono runtime can't be initialized twice in the same process."
);
let n_cstr = CString::new(name).expect(crate::STR2CSTR_ERR);
let res = unsafe {
Domain::from_ptr(version.map_or_else(
|| mono_jit_init(n_cstr.as_ptr()),
|s| {
let v_cstr = CString::new(s).expect(crate::STR2CSTR_ERR);
let ptr = mono_jit_init_version(n_cstr.as_ptr(), v_cstr.as_ptr());
let _ = &v_cstr;
ptr
},
))
};
unsafe { crate::binds::mono_jit_thread_attach(res.get_ptr()) };
let _ = &n_cstr;
*domain = Some(res);
res
}
pub fn cleanup(domain: Domain) {
unsafe { mono_jit_cleanup(domain.get_ptr()) };
}
use crate::assembly::Assembly;
pub fn exec(domain: &Domain, assembly: &Assembly, args: Vec<&str>) -> Result<i32, usize> {
#[allow(clippy::cast_possible_truncation)]
#[allow(clippy::cast_possible_wrap)]
let argument_count: i32 = (args.len() + 1) as i32;
let mut cstr_args: Vec<CString> = Vec::new();
let mut argument_vector: Vec<*mut i8> = Vec::with_capacity(args.len() + 1);
unsafe {
argument_vector.push(crate::binds::mono_stringify_assembly_name(
crate::binds::mono_assembly_get_name(assembly.get_ptr()),
));
}
for (index, arg) in args.into_iter().enumerate() {
let Ok(cstr_arg) = CString::new(arg) else {
return Err(index);
};
argument_vector.push(cstr_arg.as_ptr() as *mut i8);
cstr_args.push(cstr_arg);
}
let res = unsafe {
mono_jit_exec(
domain.get_ptr(),
assembly.get_ptr(),
argument_count,
argument_vector.as_mut_ptr(),
)
};
let _ = &cstr_args;
Ok(res)
}