mono_rt/types/method.rs
1use std::ffi::CStr;
2
3use super::{MonoObject, Value, mono_handle};
4use crate::{MonoError, Result, api};
5
6use std::ptr;
7
8mono_handle!(MonoMethod);
9
10impl MonoMethod {
11 /// Returns the name of this method as reported by the Mono runtime.
12 ///
13 /// The returned string is copied out of Mono's metadata and is safe to use beyond the
14 /// lifetime of the runtime handle.
15 ///
16 /// # Errors
17 ///
18 /// Returns [`MonoError::Uninitialized`] if the Mono API has not been initialized.
19 pub fn name(self) -> Result<String> {
20 let ptr = api()?.method_get_name(self.as_ptr());
21 if ptr.is_null() {
22 return Ok(String::new());
23 }
24 Ok(unsafe { CStr::from_ptr(ptr) }
25 .to_string_lossy()
26 .into_owned())
27 }
28
29 /// Invokes the method on `obj` (null for static methods) with the given arguments.
30 ///
31 /// Returns `Ok(Some(result))` on success, `Ok(None)` when the method returns void, and
32 /// `Err(MonoError::ManagedException(exc))` when the invocation throws a managed exception.
33 ///
34 /// # Errors
35 ///
36 /// Returns [`MonoError::ManagedException`] when a managed exception is thrown.
37 /// Returns [`MonoError::Uninitialized`] if the Mono API has not been initialized.
38 ///
39 /// # Safety
40 ///
41 /// `obj` and `args` must be valid Mono objects/arguments matching the method signature.
42 pub unsafe fn invoke(
43 self,
44 obj: *mut c_void,
45 args: *mut *mut c_void,
46 ) -> Result<Option<MonoObject>> {
47 let mut exc = ptr::null_mut::<c_void>();
48 let result = api()?.runtime_invoke(self.as_ptr(), obj, args, ptr::addr_of_mut!(exc));
49
50 if !exc.is_null() {
51 let exc_obj = unsafe { MonoObject::from_ptr_unchecked(exc) };
52 return Err(MonoError::ManagedException(exc_obj));
53 }
54
55 Ok(MonoObject::from_ptr(result))
56 }
57
58 /// Typed variant of [`invoke`](Self::invoke): builds the args array from `args` automatically.
59 ///
60 /// Prefer this over `invoke` when argument types are known at compile time. The caller is still
61 /// responsible for matching the `Value` variants to the method's actual parameter types.
62 ///
63 /// # Errors
64 ///
65 /// Returns [`MonoError::ManagedException`] when a managed exception is thrown.
66 /// Returns [`MonoError::Uninitialized`] if the Mono API has not been initialized.
67 ///
68 /// # Safety
69 ///
70 /// `obj` must be a valid Mono object pointer (or null for static methods). Each [`Value`]
71 /// in `args` must correspond to the correct parameter type expected by the method.
72 pub unsafe fn invoke_with(
73 self,
74 obj: *mut c_void,
75 args: &[Value],
76 ) -> Result<Option<MonoObject>> {
77 let mut ptrs: Vec<*mut c_void> = args.iter().map(Value::as_arg_ptr).collect();
78 let args_ptr = if ptrs.is_empty() {
79 std::ptr::null_mut()
80 } else {
81 ptrs.as_mut_ptr()
82 };
83 unsafe { self.invoke(obj, args_ptr) }
84 }
85}