wolfram_export/lib.rs
1//! Unified runtime for `#[export]`-marked Wolfram LibraryLink functions.
2//!
3//! Pick modes via Cargo features:
4//!
5//! ```toml
6//! wolfram-export = { version = "0.5", features = ["wxf"] } # typed WXF
7//! wolfram-export = { version = "0.5", features = ["wstp"] } # WSTP Link
8//! wolfram-export = "0.5" # native + margs (default)
9//! ```
10//!
11//! `#[export(margs)]` (raw `MArgument`, manual marshaling) rides on the
12//! `native` feature — there's no separate feature flag for it.
13//!
14//! Then in your code (shown here with every mode enabled):
15//!
16//! ```
17//! # // Compiled and tested only when all three feature-gated modes are enabled
18//! # // (e.g. `cargo test --all-features`); a no-op otherwise.
19//! # #[cfg(all(feature = "wstp", feature = "wxf"))]
20//! # mod scope {
21//! use wolfram_export::{export, sys::MArgument, wstp::Link};
22//!
23//! #[export] fn add(a: f64, b: f64) -> f64 { a + b }
24//! #[export(margs)] fn raw_add(args: &[MArgument], ret: MArgument) {
25//! unsafe { *ret.real = *args[0].real + *args[1].real; }
26//! }
27//! #[export(wstp)] fn echo(link: &mut Link) { let _ = link; }
28//! #[export(wxf)] fn dot(a: Vec<f64>, b: Vec<f64>) -> f64 {
29//! a.iter().zip(&b).map(|(x, y)| x * y).sum()
30//! }
31//! # }
32//! ```
33//!
34//! Each mode's wire shape, runtime, and Cargo dep set live in its own
35//! feature-gated submodule below. The `ExportEntry` inventory and the
36//! `__wolfram_manifest__` C symbol are always on (they're tiny and how the
37//! `cargo wl build` tool discovers exports).
38
39#![warn(missing_docs)]
40
41//==============================================================================
42// Always-on: shared inventory + manifest plumbing. The actual definitions live
43// in the `wolfram-export-core` workspace-internal crate (so `wolfram-library-link`
44// can depend on them without creating a cycle through `wolfram-export`).
45//==============================================================================
46
47pub use ::wolfram_export_core::ExportEntry;
48
49#[cfg(feature = "automate-function-loading-boilerplate")]
50pub use ::wolfram_export_core::exported_library_functions_association;
51
52#[cfg(feature = "automate-function-loading-boilerplate")]
53#[doc(hidden)]
54pub use ::wolfram_export_core::inventory;
55
56//==============================================================================
57// Mode-gated submodules.
58//==============================================================================
59
60/// Runtime support for native-mode exports (`#[export]`), which are called
61/// over the raw `MArgument` C ABI.
62#[cfg(feature = "native")]
63pub mod native;
64
65/// Runtime support for WSTP-mode exports (`#[export(wstp)]`), which are
66/// called over a WSTP `Link`.
67#[cfg(feature = "wstp")]
68pub mod wstp;
69
70/// Runtime support for WXF-mode exports (`#[export(wxf)]`), which exchange
71/// typed values as a WXF `ByteArray`.
72#[cfg(feature = "wxf")]
73pub mod wxf;
74
75//==============================================================================
76// Proc-macro re-exports — `wolfram_export::export` works in user code without
77// a separate `wolfram-export-macros` dep.
78//==============================================================================
79
80/// Export a function as a Wolfram LibraryLink function. See
81/// [`export`][macro@export] for the four wire-format modes (native, `margs`,
82/// `wstp`, `wxf`) and the Cargo features each one needs.
83pub use wolfram_export_macros::export;
84
85/// Designate a one-time library-load initialization function. See
86/// [`init`][macro@init].
87pub use wolfram_export_macros::init;
88
89//==============================================================================
90// Macro-emission surface.
91//
92// The proc-macro emits code that names `wolfram_export::sys::*` and
93// `wolfram_export::macro_utils::*`. These resolve via the mode submodules
94// below, gated on the matching feature.
95//==============================================================================
96
97#[cfg(any(feature = "native", feature = "wxf"))]
98pub mod sys {
99 //! Raw `wolfram-library-link-sys` C-FFI types (`WolframLibraryData`,
100 //! `MArgument`, `mint`, …). Available whenever any LibraryLink-using
101 //! mode is enabled.
102 pub use ::wolfram_library_link_sys::*;
103}
104
105#[cfg(feature = "native")]
106pub use ::wolfram_library_link::NativeFunction;
107
108/// Macro-runtime helpers. Re-exports of the per-mode `macro_utils` modules
109/// behind a single `wolfram_export::macro_utils::*` namespace so the
110/// proc-macro can emit one consistent path regardless of mode.
111pub mod macro_utils {
112 #[cfg(feature = "native")]
113 pub use crate::native::macro_utils::*;
114
115 #[cfg(feature = "wstp")]
116 pub use crate::wstp::macro_utils::*;
117
118 #[cfg(feature = "wxf")]
119 pub use ::wolfram_serialize::FromWXF;
120
121 #[cfg(feature = "wxf")]
122 pub use crate::wxf::macro_utils::*;
123
124 // The `#[export(wxf)]` bridge names `NumericArray<u8>` (the input ByteArray
125 // buffer). It's `wolfram-library-link`'s runtime type — re-exported here for
126 // macro codegen only (hidden), not as part of `wolfram-export`'s public API.
127 // Users name value types via `wolfram_library_link` directly.
128 #[cfg(feature = "wxf")]
129 #[doc(hidden)]
130 pub use ::wolfram_library_link::NumericArray;
131
132 /// `LibraryLinkFunction` is a type alias for [`ExportEntry`][crate::ExportEntry].
133 /// Lives at this path because the proc-macro emits
134 /// `macro_utils::LibraryLinkFunction::{Native,Wstp,Wxf}{...}` for inventory
135 /// submission.
136 pub use crate::ExportEntry as LibraryLinkFunction;
137}
138
139//==============================================================================
140// Feature-presence asserts.
141//
142// The proc-macro emits a `const _: () = wolfram_export::__assert_<mode>_enabled();`
143// at the top of each generated wrapper. When the matching feature is OFF, the
144// const fn body is `panic!(...)` — evaluating it in a const context becomes a
145// compile-time error with a friendly, actionable message instead of a generic
146// path-resolution failure.
147//==============================================================================
148
149#[cfg(feature = "native")]
150#[doc(hidden)]
151pub const fn __assert_native_enabled() {}
152#[cfg(not(feature = "native"))]
153#[doc(hidden)]
154pub const fn __assert_native_enabled() {
155 panic!(
156 "`#[export]` (native mode) requires enabling the `native` feature of `wolfram-export`"
157 );
158}
159
160#[cfg(feature = "native")]
161#[doc(hidden)]
162pub const fn __assert_margs_enabled() {}
163#[cfg(not(feature = "native"))]
164#[doc(hidden)]
165pub const fn __assert_margs_enabled() {
166 panic!(
167 "`#[export(margs)]` requires enabling the `native` feature of `wolfram-export`"
168 );
169}
170
171#[cfg(feature = "wstp")]
172#[doc(hidden)]
173pub const fn __assert_wstp_enabled() {}
174#[cfg(not(feature = "wstp"))]
175#[doc(hidden)]
176pub const fn __assert_wstp_enabled() {
177 panic!("`#[export(wstp)]` requires enabling the `wstp` feature of `wolfram-export`");
178}
179
180#[cfg(feature = "wxf")]
181#[doc(hidden)]
182pub const fn __assert_wxf_enabled() {}
183#[cfg(not(feature = "wxf"))]
184#[doc(hidden)]
185pub const fn __assert_wxf_enabled() {
186 panic!("`#[export(wxf)]` requires enabling the `wxf` feature of `wolfram-export`");
187}