use super::{c_string, complete, completion, failed, receive};
use emscripten_functions_sys::emscripten as ffi;
use std::{ffi::c_void, io};
unsafe extern "C" {
fn dlclose(handle: *mut c_void) -> i32;
}
pub struct Library(std::ptr::NonNull<c_void>);
impl Library {
pub fn as_ptr(&self) -> *mut c_void {
self.0.as_ptr()
}
}
impl Drop for Library {
fn drop(&mut self) {
unsafe { dlclose(self.0.as_ptr()) };
}
}
pub async unsafe fn dlopen(filename: &str, flags: i32) -> io::Result<Library> {
unsafe extern "C" fn loaded(arg: *mut c_void, handle: *mut c_void) {
let result = std::ptr::NonNull::new(handle)
.map(Library)
.ok_or_else(|| io::Error::other("dynamic library returned a null handle"));
unsafe { complete(arg, result) };
}
let filename = c_string(filename)?;
let (arg, receiver) = completion::<Library>();
unsafe {
ffi::emscripten_dlopen(
filename.as_ptr(),
flags,
arg,
Some(loaded),
Some(failed::<Library>),
)
};
receive(receiver).await
}