mono_rs/
object.rs

1use std::{
2    ffi::{c_void, CStr, CString},
3    ptr::null_mut,
4    sync::Arc,
5};
6
7use crate::{
8    assembly::Assembly,
9    bindings::{
10        mono_class_get_field_from_name, mono_class_get_name, mono_method_desc_new,
11        mono_method_desc_search_in_class, mono_runtime_invoke, MonoObject,
12    },
13    class::Class,
14    domain::Domain,
15    field::ObjectField,
16    image::Image,
17    method::{Arguments, ObjectMethod},
18    void::AsRawVoid,
19    MonoResult,
20};
21
22#[derive(Clone, Debug)]
23pub struct Object {
24    pub mono_ptr: *mut MonoObject,
25    pub assembly: Arc<Assembly>,
26    pub class: Arc<Class>,
27    pub domain: Arc<Domain>,
28    pub image: Arc<Image>,
29}
30
31impl Object {
32    pub fn construct(&self, args: Option<Arguments>) -> MonoResult<()> {
33        unsafe {
34            mono_runtime_invoke(
35                self.get_method_by_name(".ctor")?.mono_ptr,
36                self.mono_ptr as *mut c_void,
37                args.as_raw_void() as *mut *mut c_void,
38                null_mut(),
39            )
40        };
41        Ok(())
42    }
43
44    pub fn get_class_name(&self) -> String {
45        unsafe {
46            CStr::from_ptr(mono_class_get_name(self.class.mono_ptr))
47                .to_string_lossy()
48                .to_string()
49        }
50    }
51
52    pub fn get_method_by_name<T: AsRef<str>>(&self, name: T) -> MonoResult<ObjectMethod> {
53        let class_name = self.get_class_name();
54        let method_name = CString::new(format!("{}:{}()", class_name, name.as_ref()))?;
55        let method_desc = unsafe { mono_method_desc_new(method_name.as_ptr(), 0) };
56        let mono_ptr = unsafe { mono_method_desc_search_in_class(method_desc, self.class.mono_ptr) };
57
58        if mono_ptr.is_null() {
59            return Err("MonoMethod Null Error!".into());
60        }
61
62        Ok(ObjectMethod {
63            mono_ptr,
64            assembly: self.assembly.clone(),
65            class: self.class.clone(),
66            domain: self.domain.clone(),
67            image: self.image.clone(),
68            object: Arc::new(self.clone()),
69        })
70    }
71
72    pub fn get_field_by_name<T: AsRef<str>>(&self, name: T) -> MonoResult<ObjectField> {
73        let field_name = CString::new(name.as_ref())?;
74        let mono_ptr =
75            unsafe { mono_class_get_field_from_name(self.class.mono_ptr, field_name.as_ptr()) };
76
77        if mono_ptr.is_null() {
78            return Err("MonoField Null Error!".into());
79        }
80
81        Ok(ObjectField {
82            mono_ptr,
83            assembly: self.assembly.clone(),
84            class: self.class.clone(),
85            domain: self.domain.clone(),
86            image: self.image.clone(),
87            object: Arc::new(self.clone()),
88        })
89    }
90}
91
92impl AsRawVoid for Object {
93    fn as_raw_void(self) -> *mut c_void {
94        self.mono_ptr as *mut c_void
95    }
96}