33//
44// SPDX-License-Identifier: MIT OR Apache-2.0
55
6- use crate :: generator:: rust:: get_params_tokens;
6+ use crate :: generator:: rust:: { get_call_params_tokens , get_params_tokens} ;
77use crate :: {
88 generator:: { naming:: qobject:: QObjectNames , rust:: fragment:: GeneratedRustFragment } ,
99 parser:: method:: ParsedMethod ,
@@ -31,6 +31,8 @@ pub fn generate_rust_methods(
3131 cpp_class_name_rust,
3232 ) ;
3333
34+ let call_parameters = get_call_params_tokens ( & invokable. parameters ) ;
35+
3436 let return_type = & invokable. method . sig . output ;
3537
3638 let cfgs = & invokable. cfgs ;
@@ -54,24 +56,38 @@ pub fn generate_rust_methods(
5456 Some ( quote ! { unsafe } )
5557 } ;
5658
57- GeneratedRustFragment :: from_cxx_item ( parse_quote_spanned ! {
58- invokable. method. span( ) =>
59- // Note: extern "Rust" block does not need to be unsafe
60- #block_safety extern #block_type {
61- // Note that we are exposing a Rust method on the C++ type to C++
62- //
63- // CXX ends up generating the source, then we generate the matching header.
64- #[ cxx_name = #invokable_ident_cpp]
65- // Needed for QObjects to have a namespace on their type or extern block
66- //
67- // A Namespace from cxx_qt::bridge would be automatically applied to all children
68- // but to apply it to only certain types, it is needed here too
69- #cxx_namespace
70- #( #cfgs) *
71- #[ doc( hidden) ]
72- #unsafe_call fn #invokable_ident_rust( #parameter_signatures) #return_type;
73- }
74- } )
59+ let wrapper_fn = if invokable. wrap {
60+ vec ! [ parse_quote_spanned! {
61+ invokable. method. span( ) =>
62+ #unsafe_call fn #invokable_ident_rust( #parameter_signatures) #return_type {
63+ self . rust( ) . #invokable_ident_rust( #call_parameters)
64+ }
65+ } ]
66+ } else {
67+ vec ! [ ]
68+ } ;
69+
70+ GeneratedRustFragment {
71+ cxx_mod_contents : vec ! [ parse_quote_spanned! {
72+ invokable. method. span( ) =>
73+ // Note: extern "Rust" block does not need to be unsafe
74+ #block_safety extern #block_type {
75+ // Note that we are exposing a Rust method on the C++ type to C++
76+ //
77+ // CXX ends up generating the source, then we generate the matching header.
78+ #[ cxx_name = #invokable_ident_cpp]
79+ // Needed for QObjects to have a namespace on their type or extern block
80+ //
81+ // A Namespace from cxx_qt::bridge would be automatically applied to all children
82+ // but to apply it to only certain types, it is needed here too
83+ #cxx_namespace
84+ #( #cfgs) *
85+ #[ doc( hidden) ]
86+ #unsafe_call fn #invokable_ident_rust( #parameter_signatures) #return_type;
87+ }
88+ } ] ,
89+ cxx_qt_mod_contents : wrapper_fn,
90+ }
7591 } )
7692 . collect :: < Vec < _ > > ( ) ;
7793
@@ -98,10 +114,12 @@ mod tests {
98114 } ;
99115 let method3: ForeignItemFn = parse_quote ! {
100116 #[ cxx_name = "opaqueInvokable" ]
117+ #[ auto_wrap]
101118 fn opaque_invokable( self : Pin <& mut MyObject >, param: & QColor ) -> UniquePtr <QColor >;
102119 } ;
103120 let method4: ForeignItemFn = parse_quote ! {
104121 #[ cxx_name = "unsafeInvokable" ]
122+ #[ auto_wrap]
105123 unsafe fn unsafe_invokable( self : & MyObject , param: * mut T ) -> * mut T ;
106124 } ;
107125 let invokables = vec ! [
@@ -116,7 +134,7 @@ mod tests {
116134 generate_rust_methods ( & invokables. iter ( ) . collect :: < Vec < _ > > ( ) , & qobject_names) . unwrap ( ) ;
117135
118136 assert_eq ! ( generated. cxx_mod_contents. len( ) , 4 ) ;
119- assert_eq ! ( generated. cxx_qt_mod_contents. len( ) , 0 ) ;
137+ assert_eq ! ( generated. cxx_qt_mod_contents. len( ) , 2 ) ;
120138
121139 // void_invokable
122140 assert_tokens_eq (
@@ -154,6 +172,15 @@ mod tests {
154172 } ,
155173 ) ;
156174
175+ assert_tokens_eq (
176+ & generated. cxx_qt_mod_contents [ 0 ] ,
177+ quote ! {
178+ fn opaque_invokable( self : Pin <& mut MyObject >, param: & QColor ) -> UniquePtr <QColor > {
179+ self . rust( ) . opaque_invokable( param)
180+ }
181+ } ,
182+ ) ;
183+
157184 // unsafe_invokable
158185 assert_tokens_eq (
159186 & generated. cxx_mod_contents [ 3 ] ,
@@ -165,5 +192,14 @@ mod tests {
165192 }
166193 } ,
167194 ) ;
195+
196+ assert_tokens_eq (
197+ & generated. cxx_qt_mod_contents [ 1 ] ,
198+ quote ! {
199+ unsafe fn unsafe_invokable( self : & MyObject , param: * mut T ) -> * mut T {
200+ self . rust( ) . unsafe_invokable( param)
201+ }
202+ } ,
203+ ) ;
168204 }
169205}
0 commit comments