11use std:: any:: Any ;
22use std:: collections:: HashMap ;
3+ use std:: fmt:: Debug ;
34use std:: os:: raw:: c_ulonglong;
45use std:: rc:: Rc ;
6+ use std:: sync:: { Mutex , OnceLock } ;
57use unity_native_plugin_sys:: * ;
68
79#[ derive( Default , Copy , Clone , Eq , PartialEq , Hash ) ]
@@ -20,14 +22,25 @@ pub trait UnityInterfaceID {
2022}
2123
2224pub struct TesterContextInterfaces {
23- map : HashMap < InfKey , Rc < dyn UnityInterfaceBase > > ,
25+ map : Mutex < HashMap < InfKey , Rc < dyn UnityInterfaceBase > > > ,
2426 interfaces : IUnityInterfaces ,
2527}
2628
29+ impl Debug for TesterContextInterfaces {
30+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
31+ f. debug_struct ( "TesterContextInterfaces" ) . finish ( )
32+ }
33+ }
34+
35+
36+ // maybe thread safety
37+ unsafe impl Send for TesterContextInterfaces { }
38+ unsafe impl Sync for TesterContextInterfaces { }
39+
2740impl TesterContextInterfaces {
2841 pub fn new ( ) -> Self {
2942 TesterContextInterfaces {
30- map : HashMap :: < InfKey , Rc < dyn UnityInterfaceBase > > :: new ( ) ,
43+ map : Mutex :: new ( HashMap :: < InfKey , Rc < dyn UnityInterfaceBase > > :: new ( ) ) ,
3144 interfaces : IUnityInterfaces {
3245 GetInterface : Some ( get_interface) ,
3346 RegisterInterface : Some ( register_interface) ,
@@ -41,49 +54,47 @@ impl TesterContextInterfaces {
4154 unsafe { std:: mem:: transmute :: < _ , _ > ( & self . interfaces ) }
4255 }
4356
44- pub fn get_interface ( & self , guid : UnityInterfaceGUID ) -> Option < & Rc < dyn UnityInterfaceBase > > {
57+ pub fn get_interface ( & self , guid : UnityInterfaceGUID ) -> Option < Rc < dyn UnityInterfaceBase > > {
4558 self . get_interface_split ( guid. m_GUIDHigh , guid. m_GUIDLow )
4659 }
4760
4861 pub fn get_interface_split (
4962 & self ,
5063 high : :: std:: os:: raw:: c_ulonglong ,
5164 low : :: std:: os:: raw:: c_ulonglong ,
52- ) -> Option < & Rc < dyn UnityInterfaceBase > > {
53- self . map . get ( & InfKey { high, low } )
65+ ) -> Option < Rc < dyn UnityInterfaceBase > > {
66+ self . map . lock ( ) . unwrap ( ) . get ( & InfKey { high, low } ) . cloned ( )
5467 }
5568
5669 pub fn register_interface < T : UnityInterfaceBase + UnityInterfaceID > (
57- & mut self ,
70+ & self ,
5871 interface : Option < Rc < dyn UnityInterfaceBase > > ,
5972 ) {
6073 let guid = T :: get_interface_guid ( ) ;
6174 self . register_interface_split ( guid. m_GUIDHigh , guid. m_GUIDLow , interface) ;
6275 }
6376
6477 pub fn register_interface_split (
65- & mut self ,
78+ & self ,
6679 high : :: std:: os:: raw:: c_ulonglong ,
6780 low : :: std:: os:: raw:: c_ulonglong ,
6881 interface : Option < Rc < dyn UnityInterfaceBase > > ,
6982 ) {
7083 if let Some ( i) = interface {
71- self . map . insert ( InfKey { high, low } , i) ;
84+ self . map . lock ( ) . unwrap ( ) . insert ( InfKey { high, low } , i) ;
7285 } else {
73- self . map . remove ( & InfKey { high, low } ) ;
86+ self . map . lock ( ) . unwrap ( ) . remove ( & InfKey { high, low } ) ;
7487 }
7588 }
7689}
7790
78- static mut UNITY_INTERFACES : Option < TesterContextInterfaces > = None ;
91+ static UNITY_INTERFACES : OnceLock < TesterContextInterfaces > = OnceLock :: new ( ) ;
7992
8093extern "system" fn get_interface ( guid : UnityInterfaceGUID ) -> * mut IUnityInterface {
81- unsafe {
82- if let Some ( i) = UNITY_INTERFACES . as_ref ( ) . unwrap ( ) . get_interface ( guid) {
83- i. as_ref ( ) . get_unity_interface ( )
84- } else {
85- std:: ptr:: null_mut ( )
86- }
94+ if let Some ( i) = UNITY_INTERFACES . get ( ) . unwrap ( ) . get_interface ( guid) {
95+ i. as_ref ( ) . get_unity_interface ( )
96+ } else {
97+ std:: ptr:: null_mut ( )
8798 }
8899}
89100
@@ -93,16 +104,14 @@ extern "system" fn get_interface_split(
93104 high : :: std:: os:: raw:: c_ulonglong ,
94105 low : :: std:: os:: raw:: c_ulonglong ,
95106) -> * mut IUnityInterface {
96- unsafe {
97- if let Some ( i) = UNITY_INTERFACES
98- . as_ref ( )
99- . unwrap ( )
100- . get_interface_split ( high, low)
101- {
102- i. as_ref ( ) . get_unity_interface ( )
103- } else {
104- std:: ptr:: null_mut ( )
105- }
107+ if let Some ( i) = UNITY_INTERFACES
108+ . get ( )
109+ . unwrap ( )
110+ . get_interface_split ( high, low)
111+ {
112+ i. as_ref ( ) . get_unity_interface ( )
113+ } else {
114+ std:: ptr:: null_mut ( )
106115 }
107116}
108117
@@ -113,34 +122,42 @@ extern "system" fn register_interface_split(
113122) {
114123}
115124
116- pub unsafe fn get_unity_interfaces ( ) -> & ' static mut TesterContextInterfaces {
117- unsafe {
118- UNITY_INTERFACES . as_mut ( ) . unwrap ( )
119- }
125+ pub unsafe fn get_unity_interfaces ( ) -> & ' static TesterContextInterfaces {
126+ UNITY_INTERFACES . get ( ) . unwrap ( )
120127}
121128
122- pub unsafe fn get_unity_interface < T : UnityInterfaceBase + UnityInterfaceID > ( ) -> & ' static T {
129+ pub unsafe fn get_unity_interface < T : UnityInterfaceBase + UnityInterfaceID + ' static > ( ) -> Rc < T >
130+ {
123131 unsafe {
124- get_unity_interfaces ( )
125- . get_interface ( T :: get_interface_guid ( ) )
126- . unwrap ( )
127- . as_any ( )
128- . downcast_ref :: < T > ( )
129- . unwrap ( )
132+ let interface_rc = get_unity_interfaces ( )
133+ . get_interface ( T :: get_interface_guid ( ) ) . unwrap ( ) ;
134+
135+ // Rcの中身をダウンキャストして新しいRcを作成
136+ let any_ref = interface_rc. as_any ( ) ;
137+ if let Some ( _) = any_ref. downcast_ref :: < T > ( ) {
138+ // Use Rc::clone to safely create an Rc<T>
139+ // First, get a raw pointer from the original Rc
140+ let ptr = Rc :: as_ptr ( & interface_rc) ;
141+ // Successfully downcasted, so cast it safely as type T
142+ let concrete_ptr = ptr as * const T ;
143+ // Create a new Rc<T> (clone the original Rc to increase the reference count)
144+ std:: mem:: forget ( interface_rc. clone ( ) ) ; // Increase reference count
145+ Rc :: from_raw ( concrete_ptr)
146+ } else {
147+ panic ! ( "interface is not T" ) ;
148+ }
130149 }
131150}
132151
133152pub fn initialize_unity_interfaces ( ) {
134153 unsafe {
135- UNITY_INTERFACES = Some ( TesterContextInterfaces :: new ( ) ) ;
154+ UNITY_INTERFACES . set ( TesterContextInterfaces :: new ( ) ) . unwrap ( ) ;
136155 unity_native_plugin:: interface:: UnityInterfaces :: set_native_unity_interfaces (
137156 crate :: interface:: get_unity_interfaces ( ) . interfaces ( ) ,
138157 ) ;
139158 }
140159}
141160
142161pub fn finalize_unity_interfaces ( ) {
143- unsafe {
144- UNITY_INTERFACES = None ;
145- }
162+ UNITY_INTERFACES . get ( ) . unwrap ( ) . map . lock ( ) . unwrap ( ) . clear ( ) ;
146163}
0 commit comments