memlink_runtime/ffi/
loader.rs1use libloading::Library;
4use std::path::Path;
5
6use crate::error::{Error, Result};
7use crate::ffi::symbols::{LibHandle, ModuleSymbols, ModuleCallFn, ModuleInitFn, ModuleShutdownFn};
8use crate::resolver::ArtifactHandle;
9
10pub struct ModuleLoader {
11 _private: (),
12}
13
14impl ModuleLoader {
15 pub fn new() -> Self {
16 ModuleLoader { _private: () }
17 }
18
19 pub fn load(&self, artifact: ArtifactHandle) -> Result<crate::instance::ModuleInstance> {
20 let path = artifact.path().to_path_buf();
21
22 let library = unsafe { Self::dlopen(&path)? };
23 let symbols = unsafe { Self::load_symbols(library.inner())? };
24
25 Ok(crate::instance::ModuleInstance::new(
26 library.clone(),
27 symbols,
28 path,
29 ))
30 }
31
32 unsafe fn dlopen(path: &Path) -> Result<LibHandle> {
33 Library::new(path)
34 .map(LibHandle::new)
35 .map_err(|e| {
36 Error::LibraryLoadFailed(format!(
37 "Failed to load library at '{}': {}",
38 path.display(),
39 e
40 ))
41 })
42 }
43
44 unsafe fn load_symbols(library: &Library) -> Result<ModuleSymbols<'_>> {
45 let memlink_init: libloading::Symbol<ModuleInitFn> = library
46 .get(b"memlink_init\0")
47 .map_err(|e| {
48 Error::SymbolNotFound(format!("memlink_init: {}", e))
49 })?;
50
51 let memlink_call: libloading::Symbol<ModuleCallFn> = library
52 .get(b"memlink_call\0")
53 .map_err(|e| {
54 Error::SymbolNotFound(format!("memlink_call: {}", e))
55 })?;
56
57 let memlink_shutdown: libloading::Symbol<ModuleShutdownFn> = library
58 .get(b"memlink_shutdown\0")
59 .map_err(|e| {
60 Error::SymbolNotFound(format!("memlink_shutdown: {}", e))
61 })?;
62
63 Ok(ModuleSymbols::new(
64 memlink_init,
65 memlink_call,
66 memlink_shutdown,
67 ))
68 }
69}
70
71impl Default for ModuleLoader {
72 fn default() -> Self {
73 Self::new()
74 }
75}