gdnative_core/init/
macros.rs

1#![macro_use]
2
3/// Declare the API endpoint to initialize export classes on startup.
4///
5/// By default this declares an extern function named `godot_nativescript_init`.
6/// This can be overridden, for example:
7///
8/// ```ignore
9/// // Declares an extern function named custom_nativescript_init instead of
10/// // godot_nativescript_init.
11/// godot_gdnative_terminate!(my_registration_callback as custom_nativescript_init);
12/// ```
13///
14/// Overriding the default entry point names can be useful if several gdnative
15/// libraries are linked statically  to avoid name clashes.
16#[macro_export]
17macro_rules! godot_nativescript_init {
18    () => {
19        fn godot_nativescript_init_empty(_init: $crate::init::InitHandle) {}
20        $crate::godot_nativescript_init!(godot_nativescript_init_empty);
21    };
22    ($callback:ident) => {
23        $crate::godot_nativescript_init!($callback as godot_nativescript_init);
24    };
25    (_ as $fn_name:ident) => {
26        fn godot_nativescript_init_empty(_init: $crate::init::InitHandle) {}
27        $crate::godot_nativescript_init!(godot_nativescript_init_empty as $fn_name);
28    };
29    ($callback:ident as $fn_name:ident) => {
30        #[no_mangle]
31        #[doc(hidden)]
32        #[allow(unused_unsafe)]
33        pub unsafe extern "C" fn $fn_name(handle: *mut $crate::libc::c_void) {
34            if !$crate::private::is_api_bound() {
35                return;
36            }
37
38            // Compatibility warning if using in-house Godot version (not applicable for custom ones)
39            #[cfg(not(feature = "custom-godot"))]
40            {
41                use $crate::core_types::Variant;
42
43                let engine = gdnative::api::Engine::godot_singleton();
44                let info = engine.get_version_info();
45
46                if info.get("major").expect("major version") != Variant::new(3)
47                || info.get("minor").expect("minor version") != Variant::new(5)
48                || info.get("patch").expect("patch version") < Variant::new(1) {
49                    let string = info.get("string").expect("version str").to::<String>().expect("version str type");
50                    $crate::log::godot_warn!(
51                        "This godot-rust version is only compatible with Godot >= 3.5.1 and < 3.6; detected version {}.\n\
52                        GDNative mismatches may lead to subtle bugs, undefined behavior or crashes at runtime.\n\
53                	    Apply the 'custom-godot' feature if you want to use current godot-rust with another Godot engine version.",
54                        string
55                    );
56                }
57            }
58
59            $crate::private::report_panics("nativescript_init", || {
60                $crate::init::auto_register($crate::init::InitHandle::new(handle, $crate::init::InitLevel::AUTO));
61                $callback($crate::init::InitHandle::new(handle, $crate::init::InitLevel::USER));
62
63                $crate::init::diagnostics::missing_suggested_diagnostics();
64            });
65        }
66    };
67}
68
69/// Declare the API endpoint to initialize the gdnative API on startup.
70///
71/// By default this declares an extern function named `godot_gdnative_init`.
72/// This can be overridden, for example:
73///
74/// ```ignore
75/// // Declares an extern function named custom_gdnative_init instead of
76/// // godot_gdnative_init.
77/// godot_gdnative_init!(my_init_callback as custom_gdnative_init);
78/// ```
79///
80/// Overriding the default entry point names can be useful if several gdnative
81/// libraries are linked statically  to avoid name clashes.
82#[macro_export]
83macro_rules! godot_gdnative_init {
84    () => {
85        fn godot_gdnative_init_empty(_options: &$crate::init::InitializeInfo) {}
86        $crate::init::godot_gdnative_init!(godot_gdnative_init_empty);
87    };
88    (_ as $fn_name:ident) => {
89        fn godot_gdnative_init_empty(_options: &$crate::init::InitializeInfo) {}
90        $crate::init::godot_gdnative_init!(godot_gdnative_init_empty as $fn_name);
91    };
92    ($callback:ident) => {
93        $crate::init::godot_gdnative_init!($callback as godot_gdnative_init);
94    };
95    ($callback:ident as $fn_name:ident) => {
96        #[no_mangle]
97        #[doc(hidden)]
98        #[allow(unused_unsafe)]
99        pub unsafe extern "C" fn $fn_name(options: *mut $crate::sys::godot_gdnative_init_options) {
100            if !$crate::private::bind_api(options) {
101                // Can't use godot_error here because the API is not bound.
102                // Init errors should be reported by bind_api.
103                return;
104            }
105
106            $crate::private::report_panics("gdnative_init", || {
107                let init_info = $crate::init::InitializeInfo::new(options);
108                $callback(&init_info)
109            });
110        }
111    };
112}
113
114/// Declare the API endpoint invoked during shutdown.
115///
116/// By default this declares an extern function named `godot_gdnative_terminate`.
117/// This can be overridden, for example:
118///
119/// ```ignore
120/// // Declares an extern function named custom_gdnative_terminate instead of
121/// // godot_gdnative_terminate.
122/// godot_gdnative_terminate!(my_shutdown_callback as custom_gdnative_terminate);
123/// ```
124///
125/// Overriding the default entry point names can be useful if several gdnative
126/// libraries are linked statically  to avoid name clashes.
127#[macro_export]
128macro_rules! godot_gdnative_terminate {
129    () => {
130        fn godot_gdnative_terminate_empty(_term_info: &$crate::init::TerminateInfo) {}
131        $crate::init::godot_gdnative_terminate!(godot_gdnative_terminate_empty);
132    };
133    ($callback:ident) => {
134        $crate::init::godot_gdnative_terminate!($callback as godot_gdnative_terminate);
135    };
136    (_ as $fn_name:ident) => {
137        fn godot_gdnative_terminate_empty(_term_info: &$crate::init::TerminateInfo) {}
138        $crate::init::godot_gdnative_terminate!(godot_gdnative_terminate_empty as $fn_name);
139    };
140    ($callback:ident as $fn_name:ident) => {
141        #[no_mangle]
142        #[doc(hidden)]
143        #[allow(unused_unsafe)]
144        pub unsafe extern "C" fn $fn_name(
145            options: *mut $crate::sys::godot_gdnative_terminate_options,
146        ) {
147            if !$crate::private::is_api_bound() {
148                return;
149            }
150
151            $crate::private::report_panics("gdnative_terminate", || {
152                let term_info = $crate::init::TerminateInfo::new(options);
153                $callback(&term_info)
154            });
155
156            $crate::private::cleanup_internal_state();
157        }
158    };
159}
160
161/// Declare all the API endpoints necessary to initialize a NativeScript library.
162///
163/// `godot_init!(init)` is a shorthand for:
164///
165/// ```ignore
166/// godot_gdnative_init!();
167/// godot_nativescript_init!(init);
168/// godot_gdnative_terminate!();
169/// ```
170///
171/// This declares three extern functions, named `godot_gdnative_init`,
172/// `godot_nativescript_init`, and `godot_gdnative_terminate`. If you need different prefixes
173/// to avoid name clashes when multiple GDNative libraries are linked statically, please use
174/// the respective macros directly.
175#[macro_export]
176macro_rules! godot_init {
177    ($callback:ident) => {
178        $crate::init::godot_gdnative_init!();
179        $crate::init::godot_nativescript_init!($callback);
180        $crate::init::godot_gdnative_terminate!();
181    };
182}