rust_zw3d/
lib.rs

1//! ZW3D SDK 的 Rust 绑定
2//!
3//! `rust-zw3d` 为 ZW3D CAD 软件提供了安全、惯用的 Rust API 封装。
4//!
5//! ## 架构
6//!
7//! - **[`raw`]** - 原始 FFI 绑定(来自 `rust-zw3d-raw` crate)
8//! - **[`editor`]** - 编辑器交互功能(消息显示、用户输入等)
9//! - **[`commands`]** - 命令和回调注册(通常由宏自动调用)
10//!
11//! ## 快速开始
12//!
13//! ### 创建一个简单的命令
14//!
15//! ```rust,ignore
16//! use rust_zw3d::{*, editor};
17//!
18//! #[cmd]
19//! fn hello(_code: i32) -> i32 {
20//!     editor::msg_disp("Hello from Rust!");
21//!     0
22//! }
23//!
24//! // 生成模块进出点
25//! zw3d_module!(my_plugin);
26//! ```
27//!
28//! ### 编辑器交互
29//!
30//! ```rust,ignore
31//! use rust_zw3d::editor;
32//!
33//! #[cmd]
34//! fn interactive_command(_code: i32) -> i32 {
35//!     // 显示消息
36//!     editor::msg_disp("请输入角度");
37//!     
38//!     // 获取用户输入
39//!     match editor::get_angle("旋转角度:", 90.0) {
40//!         Ok(angle) => {
41//!             editor::msg_disp(&format!("旋转 {} 度", angle));
42//!             // 执行旋转操作...
43//!             0
44//!         }
45//!         Err(_) => {
46//!             editor::msg_disp("操作已取消");
47//!             1
48//!         }
49//!     }
50//! }
51//! ```
52//!
53//! ## 特性
54//!
55//! - ✅ 自动中文支持(GBK ↔ UTF-8 转换)
56//! - ✅ 类型安全的宏系统
57//! - ✅ Rust 风格的 API 封装
58//! - ✅ 完整的 FFI 绑定访问
59//!
60//! ## 相关 Crate
61//!
62//! - [`rust-zw3d-raw`](https://docs.rs/rust-zw3d-raw) - 原始 FFI 绑定
63//! - [`rust-zw3d-macros`](https://docs.rs/rust-zw3d-macros) - 过程宏
64//! - [`rust-zw3d-build`](https://docs.rs/rust-zw3d-build) - 构建工具
65
66/// 重导出原始 FFI 绑定
67///
68/// 通过 `rust_zw3d::raw` 可以访问所有底层 ZW3D C API。
69///
70/// # Examples
71///
72/// ```rust,ignore
73/// use rust_zw3d::raw;
74///
75/// // 直接调用原始 API
76/// unsafe {
77///     raw::cvxPartInqActive(&mut id);
78/// }
79/// ```
80pub use rust_zw3d_raw as raw;
81
82/// 字符串编码转换(内部使用)
83mod encoding;
84
85/// 错误类型定义
86pub mod error;
87
88/// 编辑器交互功能
89///
90/// 提供与 ZW3D 编辑器交互的高层封装。
91pub mod editor;
92
93/// 命令和回调注册(内部函数)
94///
95/// 此模块中的函数通常由宏自动调用,不需要手动使用。
96pub mod commands;
97
98// 重导出 commands 模块的内容,保持向后兼容
99pub use commands::*;
100
101// 重导出错误类型,方便使用
102pub use error::{ZwError, ZwResult};
103
104/// 当前编译所针对的 ZW3D SDK 主版本
105pub const SDK_VERSION: &str = raw::SDK_VERSION;
106
107/// 重导出 inventory 与 paste,供宏展开时通过 ::rust_zw3d::<crate> 访问
108#[doc(hidden)]
109pub use inventory;
110#[doc(hidden)]
111pub use paste;
112
113// 重导出字符串转换辅助函数,供宏生成的代码使用
114#[doc(hidden)]
115pub use encoding::{from_gbk_cstr, to_gbk_bytes};
116
117/// 当开启 `macros` feature 时,重导出属性宏
118#[cfg(feature = "macros")]
119pub use rust_zw3d_macros::{callback, cmd};
120
121/// 命令条目,用于 `inventory` 收集并在运行时统一注册。
122///
123/// 这个结构体由 `#[cmd]` 宏自动生成,通常不需要手动创建。
124#[derive(Copy, Clone)]
125pub struct Command {
126    /// 命令名称
127    pub name: &'static str,
128    /// 命令函数指针
129    pub func: *mut core::ffi::c_void,
130    /// 命令代码/类别
131    pub code: f64,
132}
133
134unsafe impl Sync for Command {}
135
136inventory::collect!(Command);
137
138/// 回调条目,用于 `inventory` 收集并在运行时统一注册。
139///
140/// 这个结构体由 `#[callback]` 宏自动生成,通常不需要手动创建。
141#[derive(Copy, Clone)]
142pub struct Callback {
143    /// 回调名称
144    pub name: &'static str,
145    /// 回调函数指针
146    pub func: *mut core::ffi::c_void,
147}
148
149unsafe impl Sync for Callback {}
150
151inventory::collect!(Callback);
152
153/// 批量注册由 `#[cmd]` 收集到的所有命令。
154#[macro_export]
155macro_rules! register_commands {
156    () => {{
157        inventory::iter::<rust_zw3d::Command>().for_each(|cmd| {
158            rust_zw3d::commands::cvxCmdFunc(cmd.name, cmd.func, cmd.code);
159        });
160    }};
161}
162
163/// 批量注册由 `#[callback]` 收集到的所有回调。
164#[macro_export]
165macro_rules! register_callbacks {
166    () => {{
167        inventory::iter::<rust_zw3d::Callback>().for_each(|cb| {
168            rust_zw3d::commands::cvxCmdCallback(cb.name, cb.func);
169        });
170    }};
171}
172
173/// 批量卸载由 `#[cmd]` 收集到的所有命令。
174#[macro_export]
175macro_rules! unregister_commands {
176    () => {{
177        inventory::iter::<rust_zw3d::Command>().for_each(|cmd| {
178            rust_zw3d::commands::cvxCmdFuncUnload(cmd.name);
179        });
180    }};
181}
182
183/// 批量卸载由 `#[callback]` 收集到的所有回调。
184#[macro_export]
185macro_rules! unregister_callbacks {
186    () => {{
187        inventory::iter::<rust_zw3d::Callback>().for_each(|cb| {
188            rust_zw3d::commands::cvxCmdCallbackUnload(cb.name);
189        });
190    }};
191}
192
193/// 生成模块进/出点:`<Name>Init` 与 `<Name>Exit`。
194///
195/// # 基本用法
196///
197/// ```rust,ignore
198/// zw3d_module!(hello);
199/// ```
200///
201/// 生成 `helloInit` 和 `helloExit` 函数,自动注册/卸载命令和回调。
202///
203/// # 带初始化函数
204///
205/// ```rust,ignore
206/// fn my_init() -> i32 {
207///     editor::msg_disp("模块初始化");
208///     0
209/// }
210///
211/// zw3d_module!(hello, init: my_init);
212/// ```
213///
214/// # 带退出函数
215///
216/// ```rust,ignore
217/// fn my_exit() -> i32 {
218///     editor::msg_disp("模块退出");
219///     0
220/// }
221///
222/// zw3d_module!(hello, exit: my_exit);
223/// ```
224///
225/// # 同时指定初始化和退出
226///
227/// ```rust,ignore
228/// zw3d_module!(hello, init: my_init, exit: my_exit);
229/// ```
230#[macro_export]
231macro_rules! zw3d_module {
232    ($modulename:ident) => {
233        ::rust_zw3d::paste::paste! {
234            #[unsafe(no_mangle)]
235            pub extern "C" fn [<$modulename Init>](_code: core::ffi::c_int, _ptr: *const core::ffi::c_void) -> core::ffi::c_int {
236                rust_zw3d::register_commands!();
237                rust_zw3d::register_callbacks!();
238                0
239            }
240
241            #[unsafe(no_mangle)]
242            pub extern "C" fn [<$modulename Exit>](_code: core::ffi::c_int, _ptr: *const core::ffi::c_void) -> core::ffi::c_int {
243                rust_zw3d::unregister_callbacks!();
244                rust_zw3d::unregister_commands!();
245                0
246            }
247        }
248    };
249
250    ($modulename:ident, init: $init_fn:expr) => {
251        ::rust_zw3d::paste::paste! {
252            #[unsafe(no_mangle)]
253            pub extern "C" fn [<$modulename Init>](_code: core::ffi::c_int, _ptr: *const core::ffi::c_void) -> core::ffi::c_int {
254                let result = $init_fn();
255                if result != 0 {
256                    return result;
257                }
258
259                rust_zw3d::register_commands!();
260                rust_zw3d::register_callbacks!();
261                0
262            }
263
264            #[unsafe(no_mangle)]
265            pub extern "C" fn [<$modulename Exit>](_code: core::ffi::c_int, _ptr: *const core::ffi::c_void) -> core::ffi::c_int {
266                rust_zw3d::unregister_callbacks!();
267                rust_zw3d::unregister_commands!();
268                0
269            }
270        }
271    };
272
273    ($modulename:ident, exit: $exit_fn:expr) => {
274        ::rust_zw3d::paste::paste! {
275            #[unsafe(no_mangle)]
276            pub extern "C" fn [<$modulename Init>](_code: core::ffi::c_int, _ptr: *const core::ffi::c_void) -> core::ffi::c_int {
277                rust_zw3d::register_commands!();
278                rust_zw3d::register_callbacks!();
279                0
280            }
281
282            #[unsafe(no_mangle)]
283            pub extern "C" fn [<$modulename Exit>](_code: core::ffi::c_int, _ptr: *const core::ffi::c_void) -> core::ffi::c_int {
284                rust_zw3d::unregister_callbacks!();
285                rust_zw3d::unregister_commands!();
286
287                $exit_fn()
288            }
289        }
290    };
291
292    ($modulename:ident, init: $init_fn:expr, exit: $exit_fn:expr) => {
293        ::rust_zw3d::paste::paste! {
294            #[unsafe(no_mangle)]
295            pub extern "C" fn [<$modulename Init>](_code: core::ffi::c_int, _ptr: *const core::ffi::c_void) -> core::ffi::c_int {
296                let result = $init_fn();
297                if result != 0 {
298                    return result;
299                }
300
301                rust_zw3d::register_commands!();
302                rust_zw3d::register_callbacks!();
303                0
304            }
305
306            #[unsafe(no_mangle)]
307            pub extern "C" fn [<$modulename Exit>](_code: core::ffi::c_int, _ptr: *const core::ffi::c_void) -> core::ffi::c_int {
308                rust_zw3d::unregister_callbacks!();
309                rust_zw3d::unregister_commands!();
310
311                $exit_fn()
312            }
313        }
314    };
315}