rusteal_core/
dynamic_call.rs1use rusteal_ffi::{FPropertyHandle, UFunctionHandle, UObjectHandle};
8
9use crate::error::{check_ffi, RustealError, RustealResult};
10use crate::ffi_dispatch::{self, NativePtr, NATIVE_PTR_NULL, native_ptr_is_null};
11use crate::object_ref::UObjectRef;
12use crate::traits::UeClass;
13
14pub struct DynamicCall {
24 obj: UObjectHandle,
25 func: UFunctionHandle,
26 params: NativePtr,
27}
28
29impl DynamicCall {
30 pub fn new(obj: &UObjectRef<impl UeClass>, func_name: &str) -> RustealResult<Self> {
32 let h = obj.checked()?.raw();
33 let func = unsafe {
34 ffi_dispatch::reflection_find_function(h, func_name.as_ptr(), func_name.len() as u32)
35 };
36 if func.is_null() {
37 return Err(RustealError::FunctionNotFound(func_name.to_string()));
38 }
39 let params = unsafe { ffi_dispatch::reflection_alloc_params(func) };
40 Ok(DynamicCall {
41 obj: h,
42 func,
43 params,
44 })
45 }
46
47 pub fn set<T: Copy>(&mut self, name: &str, value: T) -> RustealResult<()> {
54 let (prop, offset) = self.find_param(name)?;
55 let _ = prop; unsafe {
59 ffi_dispatch::native_mem_write(self.params, offset as usize, value);
60 }
61 Ok(())
62 }
63
64 pub fn call(mut self) -> RustealResult<DynamicCallResult> {
67 let code =
68 unsafe { ffi_dispatch::reflection_call_function(self.obj, self.func, self.params) };
69 check_ffi(code)?;
70 let result = DynamicCallResult {
72 func: self.func,
73 params: self.params,
74 };
75 self.params = NATIVE_PTR_NULL;
77 Ok(result)
78 }
79
80 fn find_param(&self, name: &str) -> RustealResult<(FPropertyHandle, u32)> {
82 let prop = unsafe {
83 ffi_dispatch::reflection_get_function_param(self.func, name.as_ptr(), name.len() as u32)
84 };
85 if prop.is_null() {
86 return Err(RustealError::PropertyNotFound(name.to_string()));
87 }
88 let offset = unsafe { ffi_dispatch::reflection_get_property_offset(prop) };
89 Ok((prop, offset))
90 }
91}
92
93impl Drop for DynamicCall {
94 fn drop(&mut self) {
95 if !native_ptr_is_null(self.params) {
96 unsafe { ffi_dispatch::reflection_free_params(self.func, self.params) };
97 }
98 }
99}
100
101pub struct DynamicCallResult {
104 func: UFunctionHandle,
105 params: NativePtr,
106}
107
108impl DynamicCallResult {
109 pub fn get<T: Copy>(&self, name: &str) -> RustealResult<T> {
114 let prop = unsafe {
115 ffi_dispatch::reflection_get_function_param(self.func, name.as_ptr(), name.len() as u32)
116 };
117 if prop.is_null() {
118 return Err(RustealError::PropertyNotFound(name.to_string()));
119 }
120 let offset = unsafe { ffi_dispatch::reflection_get_property_offset(prop) };
121 let value = unsafe { ffi_dispatch::native_mem_read(self.params, offset as usize) };
124 Ok(value)
125 }
126}
127
128impl Drop for DynamicCallResult {
129 fn drop(&mut self) {
130 if !native_ptr_is_null(self.params) {
131 unsafe { ffi_dispatch::reflection_free_params(self.func, self.params) };
132 }
133 }
134}