1#[cfg(feature = "wstp")]
2use std::thread;
3
4use once_cell::sync::OnceCell;
5
6use crate::sys::{
7 self, mbool, mcomplex, mint, mreal, st_WolframCompileLibrary_Functions,
8 st_WolframIOLibrary_Functions, st_WolframImageLibrary_Functions,
9 st_WolframNumericArrayLibrary_Functions, st_WolframRawArrayLibrary_Functions,
10 st_WolframRuntimeData, st_WolframSparseLibrary_Functions, MArgument, MInputStream,
11 MOutputStream, MTensor, WSENV, WSLINK,
12};
13
14#[derive(Copy, Clone)]
15struct Data {
16 #[cfg(feature = "wstp")]
24 main_thread_id: thread::ThreadId,
25 library_data: WolframLibraryData,
26}
27
28static LIBRARY_DATA: OnceCell<Data> = OnceCell::new();
29
30pub unsafe fn initialize(data: sys::WolframLibraryData) -> Result<(), ()> {
80 let library_data = WolframLibraryData::new(data)?;
81
82 let _: Result<(), Data> = LIBRARY_DATA.set(Data {
83 #[cfg(feature = "wstp")]
84 main_thread_id: thread::current().id(),
85 library_data,
86 });
87
88 Ok(())
89}
90
91pub fn get_library_data() -> WolframLibraryData {
96 let data: Option<&_> = LIBRARY_DATA.get();
97
98 data.expect(
101 "get_library_data: global Wolfram LIBRARY_DATA static is not initialized.",
102 )
103 .library_data
104}
105
106#[cfg(feature = "wstp")]
107pub(crate) fn is_main_thread() -> bool {
108 let data = LIBRARY_DATA
109 .get()
110 .expect("global LIBRARY_DATA static is not initialized");
111
112 data.main_thread_id == thread::current().id()
113}
114
115#[cfg(feature = "wstp")]
124#[track_caller]
125pub(crate) fn assert_main_thread() {
126 let loc = std::panic::Location::caller();
127
128 assert!(
129 is_main_thread(),
130 "error: attempted to call back into the Wolfram Kernel from a non-main thread at {}:{}",
131 loc.file(),
132 loc.line()
133 );
134}
135
136#[allow(non_snake_case)]
137#[derive(Copy, Clone)]
138#[allow(missing_docs)]
139pub struct WolframLibraryData {
140 pub raw_library_data: sys::WolframLibraryData,
141
142 pub UTF8String_disown: unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_char),
143
144 pub MTensor_new: unsafe extern "C" fn(
145 arg1: mint,
146 arg2: mint,
147 arg3: *const mint,
148 arg4: *mut MTensor,
149 ) -> ::std::os::raw::c_int,
150
151 pub MTensor_free: unsafe extern "C" fn(arg1: MTensor),
152
153 pub MTensor_clone:
154 unsafe extern "C" fn(arg1: MTensor, arg2: *mut MTensor) -> ::std::os::raw::c_int,
155
156 pub MTensor_shareCount: unsafe extern "C" fn(arg1: MTensor) -> mint,
157
158 pub MTensor_disown: unsafe extern "C" fn(arg1: MTensor),
159
160 pub MTensor_disownAll: unsafe extern "C" fn(arg1: MTensor),
161
162 pub MTensor_setInteger: unsafe extern "C" fn(
163 arg1: MTensor,
164 arg2: *mut mint,
165 arg3: mint,
166 ) -> ::std::os::raw::c_int,
167
168 pub MTensor_setReal: unsafe extern "C" fn(
169 arg1: MTensor,
170 arg2: *mut mint,
171 arg3: mreal,
172 ) -> ::std::os::raw::c_int,
173
174 pub MTensor_setComplex: unsafe extern "C" fn(
175 arg1: MTensor,
176 arg2: *mut mint,
177 arg3: mcomplex,
178 ) -> ::std::os::raw::c_int,
179
180 pub MTensor_setMTensor: unsafe extern "C" fn(
181 arg1: MTensor,
182 arg2: MTensor,
183 arg3: *mut mint,
184 arg4: mint,
185 ) -> ::std::os::raw::c_int,
186
187 pub MTensor_getInteger: unsafe extern "C" fn(
188 arg1: MTensor,
189 arg2: *mut mint,
190 arg3: *mut mint,
191 ) -> ::std::os::raw::c_int,
192
193 pub MTensor_getReal: unsafe extern "C" fn(
194 arg1: MTensor,
195 arg2: *mut mint,
196 arg3: *mut mreal,
197 ) -> ::std::os::raw::c_int,
198
199 pub MTensor_getComplex: unsafe extern "C" fn(
200 arg1: MTensor,
201 arg2: *mut mint,
202 arg3: *mut mcomplex,
203 ) -> ::std::os::raw::c_int,
204
205 pub MTensor_getMTensor: unsafe extern "C" fn(
206 arg1: MTensor,
207 arg2: *mut mint,
208 arg3: mint,
209 arg4: *mut MTensor,
210 ) -> ::std::os::raw::c_int,
211
212 pub MTensor_getRank: unsafe extern "C" fn(arg1: MTensor) -> mint,
213 pub MTensor_getDimensions: unsafe extern "C" fn(arg1: MTensor) -> *const mint,
214 pub MTensor_getType: unsafe extern "C" fn(arg1: MTensor) -> mint,
215 pub MTensor_getFlattenedLength: unsafe extern "C" fn(arg1: MTensor) -> mint,
216 pub MTensor_getIntegerData: unsafe extern "C" fn(arg1: MTensor) -> *mut mint,
217 pub MTensor_getRealData: unsafe extern "C" fn(arg1: MTensor) -> *mut mreal,
218 pub MTensor_getComplexData: unsafe extern "C" fn(arg1: MTensor) -> *mut mcomplex,
219
220 pub Message: unsafe extern "C" fn(arg1: *const ::std::os::raw::c_char),
221 pub AbortQ: unsafe extern "C" fn() -> mint,
222
223 pub getWSLINK: unsafe extern "C" fn(arg1: sys::WolframLibraryData) -> WSLINK,
224 pub processWSLINK: unsafe extern "C" fn(arg1: WSLINK) -> ::std::os::raw::c_int,
225
226 pub evaluateExpression: unsafe extern "C" fn(
227 arg1: sys::WolframLibraryData,
228 arg2: *mut ::std::os::raw::c_char,
229 arg3: ::std::os::raw::c_int,
230 arg4: mint,
231 arg5: *mut ::std::os::raw::c_void,
232 ) -> ::std::os::raw::c_int,
233
234 pub runtimeData: *mut st_WolframRuntimeData,
235
236 pub compileLibraryFunctions: *mut st_WolframCompileLibrary_Functions,
237
238 pub VersionNumber: mint,
239
240 pub registerInputStreamMethod: unsafe extern "C" fn(
241 name: *const ::std::os::raw::c_char,
242 ctor: Option<
243 unsafe extern "C" fn(
244 arg1: MInputStream,
245 msgHead: *const ::std::os::raw::c_char,
246 optionsIn: *mut ::std::os::raw::c_void,
247 ),
248 >,
249 handlerTest: Option<
250 unsafe extern "C" fn(
251 arg1: *mut ::std::os::raw::c_void,
252 arg2: *mut ::std::os::raw::c_char,
253 ) -> mbool,
254 >,
255 methodData: *mut ::std::os::raw::c_void,
256 destroyMethod: Option<
257 unsafe extern "C" fn(methodData: *mut ::std::os::raw::c_void),
258 >,
259 ) -> mbool,
260
261 pub unregisterInputStreamMethod:
262 unsafe extern "C" fn(name: *const ::std::os::raw::c_char) -> mbool,
263
264 pub registerOutputStreamMethod: unsafe extern "C" fn(
265 name: *const ::std::os::raw::c_char,
266 ctor: Option<
267 unsafe extern "C" fn(
268 arg1: MOutputStream,
269 msgHead: *const ::std::os::raw::c_char,
270 optionsIn: *mut ::std::os::raw::c_void,
271 appendMode: mbool,
272 ),
273 >,
274 handlerTest: Option<
275 unsafe extern "C" fn(
276 arg1: *mut ::std::os::raw::c_void,
277 arg2: *mut ::std::os::raw::c_char,
278 ) -> mbool,
279 >,
280 methodData: *mut ::std::os::raw::c_void,
281 destroyMethod: Option<
282 unsafe extern "C" fn(methodData: *mut ::std::os::raw::c_void),
283 >,
284 ) -> mbool,
285
286 pub unregisterOutputStreamMethod:
287 unsafe extern "C" fn(name: *const ::std::os::raw::c_char) -> mbool,
288
289 pub ioLibraryFunctions: *mut st_WolframIOLibrary_Functions,
290
291 pub getWSLINKEnvironment:
292 unsafe extern "C" fn(arg1: sys::WolframLibraryData) -> WSENV,
293
294 pub sparseLibraryFunctions: *mut st_WolframSparseLibrary_Functions,
295
296 pub imageLibraryFunctions: *mut st_WolframImageLibrary_Functions,
297
298 pub registerLibraryExpressionManager: unsafe extern "C" fn(
299 mname: *const ::std::os::raw::c_char,
300 mfun: Option<
301 unsafe extern "C" fn(arg1: sys::WolframLibraryData, arg2: mbool, arg3: mint),
302 >,
303 )
304 -> ::std::os::raw::c_int,
305
306 pub unregisterLibraryExpressionManager: unsafe extern "C" fn(
307 mname: *const ::std::os::raw::c_char,
308 )
309 -> ::std::os::raw::c_int,
310
311 pub releaseManagedLibraryExpression: unsafe extern "C" fn(
312 mname: *const ::std::os::raw::c_char,
313 id: mint,
314 )
315 -> ::std::os::raw::c_int,
316
317 pub registerLibraryCallbackManager: unsafe extern "C" fn(
318 name: *const ::std::os::raw::c_char,
319 mfun: Option<
320 unsafe extern "C" fn(
321 arg1: sys::WolframLibraryData,
322 arg2: mint,
323 arg3: MTensor,
324 ) -> mbool,
325 >,
326 )
327 -> ::std::os::raw::c_int,
328
329 pub unregisterLibraryCallbackManager: unsafe extern "C" fn(
330 name: *const ::std::os::raw::c_char,
331 )
332 -> ::std::os::raw::c_int,
333
334 pub callLibraryCallbackFunction: unsafe extern "C" fn(
335 id: mint,
336 ArgC: mint,
337 Args: *mut MArgument,
338 Res: MArgument,
339 ) -> ::std::os::raw::c_int,
340
341 pub releaseLibraryCallbackFunction:
342 unsafe extern "C" fn(id: mint) -> ::std::os::raw::c_int,
343
344 pub validatePath: unsafe extern "C" fn(
345 path: *mut ::std::os::raw::c_char,
346 type_: ::std::os::raw::c_char,
347 ) -> mbool,
348
349 pub protectedModeQ: unsafe extern "C" fn() -> mbool,
350 pub rawarrayLibraryFunctions: *mut st_WolframRawArrayLibrary_Functions,
351 pub numericarrayLibraryFunctions: *mut st_WolframNumericArrayLibrary_Functions,
352 pub setParallelThreadNumber:
353 unsafe extern "C" fn(arg1: ::std::os::raw::c_int) -> ::std::os::raw::c_int,
354 pub restoreParallelThreadNumber: unsafe extern "C" fn(arg1: ::std::os::raw::c_int),
355 pub getParallelThreadNumber: unsafe extern "C" fn() -> ::std::os::raw::c_int,
356}
357
358unsafe impl Send for WolframLibraryData {}
371unsafe impl Sync for WolframLibraryData {}
372
373macro_rules! unwrap_fields {
374 ($raw:expr, $data:expr, [ $($field:ident),+ ]) => {{
375 WolframLibraryData {
376 raw_library_data: $raw,
377 VersionNumber: $data.VersionNumber,
378 runtimeData: $data.runtimeData,
379 compileLibraryFunctions: $data.compileLibraryFunctions,
380 rawarrayLibraryFunctions: $data.rawarrayLibraryFunctions,
381 numericarrayLibraryFunctions: $data.numericarrayLibraryFunctions,
382 sparseLibraryFunctions: $data.sparseLibraryFunctions,
383 imageLibraryFunctions: $data.imageLibraryFunctions,
384 ioLibraryFunctions: $data.ioLibraryFunctions,
385 $($field: $data.$field.unwrap()),+,
386 }
387 }}
388}
389
390impl WolframLibraryData {
391 pub fn new(data_ptr: sys::WolframLibraryData) -> Result<Self, ()> {
393 if data_ptr.is_null() {
394 return Err(());
395 }
396
397 let data: sys::st_WolframLibraryData = unsafe { *data_ptr };
398
399 Ok(unwrap_fields!(
400 data_ptr,
401 data,
402 [
403 UTF8String_disown,
404 MTensor_new,
405 MTensor_free,
406 MTensor_clone,
407 MTensor_shareCount,
408 MTensor_disown,
409 MTensor_disownAll,
410 MTensor_setInteger,
411 MTensor_setReal,
412 MTensor_setComplex,
413 MTensor_setMTensor,
414 MTensor_getInteger,
415 MTensor_getReal,
416 MTensor_getComplex,
417 MTensor_getMTensor,
418 MTensor_getRank,
419 MTensor_getDimensions,
420 MTensor_getType,
421 MTensor_getFlattenedLength,
422 MTensor_getIntegerData,
423 MTensor_getRealData,
424 MTensor_getComplexData,
425 Message,
426 AbortQ,
427 getWSLINK,
428 processWSLINK,
429 evaluateExpression,
430 registerInputStreamMethod,
431 unregisterInputStreamMethod,
432 registerOutputStreamMethod,
433 unregisterOutputStreamMethod,
434 getWSLINKEnvironment,
435 registerLibraryExpressionManager,
436 unregisterLibraryExpressionManager,
437 releaseManagedLibraryExpression,
438 registerLibraryCallbackManager,
439 unregisterLibraryCallbackManager,
440 callLibraryCallbackFunction,
441 releaseLibraryCallbackFunction,
442 validatePath,
443 protectedModeQ,
444 setParallelThreadNumber,
445 restoreParallelThreadNumber,
446 getParallelThreadNumber
447 ]
448 ))
449 }
450}