Skip to main content

mono_rt/types/
assembly.rs

1use std::ffi::{CString, c_char};
2
3use super::{MonoImage, mono_handle};
4use crate::{MonoError, MonoImageOpenStatus, Result, api};
5
6mono_handle!(MonoAssembly);
7
8impl MonoAssembly {
9    /// Registers a `MonoImage` as a fully loaded assembly in the current domain.
10    ///
11    /// `base_dir` is the directory hint Mono uses to resolve dependent assemblies. Pass `None`
12    /// to rely on the standard assembly search path (correct for most injection scenarios).
13    ///
14    /// # Errors
15    ///
16    /// Returns [`MonoError::NullByteInName`] if `base_dir` contains an interior null byte.
17    /// Returns [`MonoError::ImageOpenFailed`] if Mono rejects the image.
18    /// Returns [`MonoError::Uninitialized`] if the Mono API has not been initialized.
19    pub fn load_from_image(image: MonoImage, base_dir: Option<&str>) -> Result<Option<Self>> {
20        // dir_c must outlive dir_ptr — hoisted here so it lives for the whole function body.
21        let dir_c;
22        let dir_ptr: *const c_char = if let Some(s) = base_dir {
23            dir_c = CString::new(s).map_err(|_| MonoError::NullByteInName)?;
24            dir_c.as_ptr()
25        } else {
26            c"".as_ptr()
27        };
28
29        let mut status: i32 = 0;
30        let ptr = api()?.assembly_load_from_full(
31            image.as_ptr(),
32            dir_ptr,
33            std::ptr::addr_of_mut!(status),
34            0,
35        );
36
37        let s = MonoImageOpenStatus::from_raw(status);
38        if !s.is_ok() {
39            return Err(MonoError::ImageOpenFailed(s));
40        }
41
42        if ptr.is_null() {
43            return Err(MonoError::ImageOpenFailed(s));
44        }
45
46        Ok(MonoAssembly::from_ptr(ptr))
47    }
48
49    /// Unloads this assembly from the runtime.
50    ///
51    /// Call this during ejection after invoking the managed unload method. Using any handle
52    /// derived from this assembly after `close` is undefined behavior.
53    ///
54    /// # Errors
55    ///
56    /// Returns [`MonoError::Uninitialized`] if the Mono API has not been initialized.
57    pub fn close(self) -> Result<()> {
58        api()?.assembly_close(self.as_ptr());
59        Ok(())
60    }
61
62    /// Returns the metadata image for this assembly.
63    ///
64    /// # Errors
65    ///
66    /// Returns [`crate::MonoError::Uninitialized`] if the Mono API has not been initialized.
67    pub fn image(self) -> Result<Option<MonoImage>> {
68        let ptr = api()?.assembly_get_image(self.as_ptr());
69        Ok(MonoImage::from_ptr(ptr))
70    }
71}