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