Skip to content

Commit e24287f

Browse files
committed
Fix and test unsafe_impl_type macros on generic types
1 parent e04ee79 commit e24287f

File tree

11 files changed

+55
-34
lines changed

11 files changed

+55
-34
lines changed

README.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,6 @@ use quest_hook::hook;
4343
use quest_hook::libil2cpp::{Il2CppObject, Il2CppString};
4444
use tracing::debug;
4545

46-
#[no_mangle]
47-
pub extern "C" fn setup() {
48-
quest_hook::setup("hello world");
49-
}
50-
5146
#[hook("UnityEngine.SceneManagement", "SceneManager", "SetActiveScene")]
5247
fn set_active_scene(scene: &mut Il2CppObject) -> bool {
5348
let name: &Il2CppString = scene.invoke("get_name", ()).unwrap();
@@ -60,6 +55,11 @@ fn set_active_scene(scene: &mut Il2CppObject) -> bool {
6055
pub extern "C" fn load() {
6156
set_active_scene.install().unwrap();
6257
}
58+
59+
#[no_mangle]
60+
pub extern "C" fn setup() {
61+
quest_hook::setup("hello world");
62+
}
6363
```
6464

6565
Check out the [`examples`](./examples/) directory for more examples.

examples/custom_type.rs

+16-7
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
1-
#![feature(generic_associated_types)]
1+
#![feature(generic_associated_types, once_cell)]
22

3+
use libil2cpp::{Il2CppArray, Type};
34
use quest_hook::hook;
4-
use quest_hook::libil2cpp::{unsafe_impl_value_type, Il2CppObject};
5+
use quest_hook::libil2cpp::{unsafe_impl_reference_type, unsafe_impl_value_type, Il2CppObject};
56
use tracing::debug;
67

7-
#[no_mangle]
8-
pub extern "C" fn setup() {
9-
quest_hook::setup("custom type");
10-
}
11-
128
#[derive(Debug)]
139
#[repr(C)]
1410
pub struct Vector3 {
@@ -26,7 +22,20 @@ fn set_position(this: &mut Il2CppObject, new_position: Vector3) {
2622
set_position.original(this, new_position)
2723
}
2824

25+
#[no_mangle]
26+
pub extern "C" fn setup() {
27+
quest_hook::setup("custom type");
28+
}
29+
2930
#[no_mangle]
3031
pub extern "C" fn load() {
3132
set_position.install().unwrap();
3233
}
34+
35+
#[repr(C)]
36+
pub struct List<T: Type> {
37+
object: Il2CppObject,
38+
items: *mut Il2CppArray<T>,
39+
size: i32,
40+
}
41+
unsafe_impl_reference_type!(in quest_hook::libil2cpp for List<T> => System.Collections.Generic.List<T>);

examples/hello_world.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,6 @@ use quest_hook::hook;
22
use quest_hook::libil2cpp::{Il2CppObject, Il2CppString};
33
use tracing::debug;
44

5-
#[no_mangle]
6-
pub extern "C" fn setup() {
7-
quest_hook::setup("hello world");
8-
}
9-
105
#[hook("UnityEngine.SceneManagement", "SceneManager", "SetActiveScene")]
116
fn set_active_scene(scene: &mut Il2CppObject) -> bool {
127
let name: &Il2CppString = scene.invoke("get_name", ()).unwrap();
@@ -15,6 +10,11 @@ fn set_active_scene(scene: &mut Il2CppObject) -> bool {
1510
set_active_scene.original(scene)
1611
}
1712

13+
#[no_mangle]
14+
pub extern "C" fn setup() {
15+
quest_hook::setup("hello world");
16+
}
17+
1818
#[no_mangle]
1919
pub extern "C" fn load() {
2020
set_active_scene.install().unwrap();

libil2cpp/src/array.rs

+4-7
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,15 @@ pub struct Il2CppArray<T: Type>(raw::Il2CppArray, PhantomData<[T]>);
1111

1212
impl<T: Type> Il2CppArray<T> {
1313
/// Creates an array from a slice
14-
pub fn from_slice<'a>(slice: &'a [T::Held<'a>]) -> &'a Self
15-
where
16-
T::Held<'a>: Clone,
17-
{
18-
let len = slice.len();
14+
pub fn new<'a>(items: Vec<T::Held<'a>>) -> &'a mut Self {
15+
let len = items.len();
1916
let arr = unsafe { raw::array_new(T::class().raw(), len) }.unwrap();
2017
let data_ptr =
2118
((arr as *mut _ as isize) + (raw::kIl2CppSizeOfArray as isize)) as *mut T::Held<'a>;
22-
for (i, elem) in slice.iter().enumerate() {
19+
for (i, elem) in items.into_iter().enumerate() {
2320
unsafe {
2421
let ptr = data_ptr.add(i);
25-
ptr::write_unaligned(ptr, elem.clone());
22+
ptr::write_unaligned(ptr, elem);
2623
}
2724
}
2825
unsafe { Self::wrap_mut(arr) }

libil2cpp/src/class.rs

+3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ type FieldInfoSlice<'a> = &'a [&'static FieldInfo];
1616
#[repr(transparent)]
1717
pub struct Il2CppClass(raw::Il2CppClass);
1818

19+
unsafe impl Send for Il2CppClass {}
20+
unsafe impl Sync for Il2CppClass {}
21+
1922
impl Il2CppClass {
2023
/// Find a class by namespace and name
2124
#[crate::instrument(level = "debug")]

libil2cpp/src/field_info.rs

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ use crate::{raw, Argument, Il2CppClass, Il2CppObject, Il2CppType, Type, WrapRaw}
99
#[repr(transparent)]
1010
pub struct FieldInfo(raw::FieldInfo);
1111

12+
unsafe impl Send for FieldInfo {}
13+
unsafe impl Sync for FieldInfo {}
14+
1215
impl FieldInfo {
1316
/// Store a typechecked value into a field
1417
pub fn store<A>(&self, instance: &mut Il2CppObject, val: A)

libil2cpp/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070
rustdoc::broken_intra_doc_links,
7171
rustdoc::private_intra_doc_links
7272
)]
73-
#![allow(clippy::single_component_path_imports)]
73+
#![allow(clippy::mut_from_ref, clippy::single_component_path_imports)]
7474

7575
//! Wrappers and raw bindings for Unity's libil2cpp
7676

libil2cpp/src/method_info.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ type ParameterInfoSlice<'a> = &'a [&'static ParameterInfo];
2121
#[repr(transparent)]
2222
pub struct MethodInfo(raw::MethodInfo);
2323

24+
unsafe impl Send for MethodInfo {}
25+
unsafe impl Sync for MethodInfo {}
26+
2427
impl MethodInfo {
2528
/// Invoke this method, type checking against its signature with the
2629
/// provided instance, arguments and return type
@@ -81,7 +84,7 @@ impl MethodInfo {
8184
// }
8285

8386
/// [`Il2CppReflectionMethod`] which represents the method
84-
pub fn reflection_object(&self) -> &'static mut Il2CppReflectionMethod {
87+
pub fn reflection_object(&self) -> &mut Il2CppReflectionMethod {
8588
unsafe { Il2CppReflectionMethod::wrap_mut(raw::method_get_object(self.raw(), None)) }
8689
}
8790

libil2cpp/src/parameter_info.rs

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ use crate::{raw, Il2CppType, WrapRaw};
88
#[repr(transparent)]
99
pub struct ParameterInfo(raw::ParameterInfo);
1010

11+
unsafe impl Send for ParameterInfo {}
12+
unsafe impl Sync for ParameterInfo {}
13+
1114
impl ParameterInfo {
1215
/// Name of the parameter
1316
pub fn name(&self) -> Cow<'_, str> {

libil2cpp/src/ty.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ use crate::{Il2CppClass, Il2CppObject, WrapRaw};
1919
#[repr(transparent)]
2020
pub struct Il2CppType(raw::Il2CppType);
2121

22+
unsafe impl Send for Il2CppType {}
23+
unsafe impl Sync for Il2CppType {}
24+
2225
impl Il2CppType {
2326
/// Class of the type
2427
pub fn class(&self) -> &Il2CppClass {
@@ -42,7 +45,7 @@ impl Il2CppType {
4245
}
4346

4447
/// [`Il2CppReflectionType`] which represents the type
45-
pub fn reflection_object(&self) -> &'static mut Il2CppReflectionType {
48+
pub fn reflection_object(&self) -> &mut Il2CppReflectionType {
4649
unsafe { Il2CppReflectionType::wrap_mut(raw::type_get_object(self.raw())) }
4750
}
4851
}

proc_macros/src/impl_type.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ impl Input {
146146

147147
fn reflection_type_ty(&self) -> TokenStream2 {
148148
let path = &self.path;
149-
quote!(#path :: Il2CppType)
149+
quote!(#path :: Il2CppReflectionType)
150150
}
151151

152152
fn array_ty(&self) -> TokenStream2 {
@@ -192,14 +192,14 @@ impl Input {
192192

193193
Some(quote! {
194194
fn class() -> &'static #class_ty {
195-
static CLASS: ::std::lazy::SyncLazy<&'static Il2CppClass> = ::std::lazy::SyncLazy::new(|| {
195+
static CLASS: ::std::lazy::SyncOnceCell<&'static #class_ty> = ::std::lazy::SyncOnceCell::new();
196+
CLASS.get_or_init(|| {
196197
let reflection_type_class = <#reflection_type_ty as #type_trait>::class();
197198
let generic_ty = #class_ty::find(#namespace, #generic_class).unwrap().ty().reflection_object();
198-
let generic_ty = unsafe { &mut *(generic_ty as *const _ as *mut _) };
199-
let generics = #array_ty::from_slice(&[#(<#generics as #type_trait>::class()),*]);
200-
reflection_type_class.invoke("MakeGenericType", (generic_ty, generics)).unwrap()
201-
});
202-
*class
199+
let generics = #array_ty::<#reflection_type_ty>::new(vec![#(Some(<#generics as #type_trait>::class().ty().reflection_object())),*]);
200+
let reflection_type: &#reflection_type_ty = reflection_type_class.invoke("MakeGenericType", (generic_ty, generics)).unwrap();
201+
reflection_type.ty().class()
202+
})
203203
}
204204
})
205205
}

0 commit comments

Comments
 (0)