Skip to main content

nsi_ffi_wrap/
lib.rs

1#![cfg_attr(feature = "nightly", feature(doc_cfg))]
2#![allow(non_snake_case)]
3//#![warn(missing_docs)]
4//#![warn(missing_doc_code_examples)]
5
6use nsi_sys::*;
7use std::{ffi::c_char, os::raw::c_int};
8
9// Re-export dependencies needed by the macro
10#[cfg(not(feature = "link_lib3delight"))]
11#[doc(hidden)]
12pub use dlopen2;
13#[doc(hidden)]
14pub extern crate lazy_static;
15#[doc(hidden)]
16pub use nsi_sys;
17
18pub mod node;
19pub use node::*;
20
21mod handle;
22pub use handle::Handle;
23use handle::HandleString;
24
25mod token;
26pub use token::Token;
27
28// Crate features -----------------------------------------------------
29
30#[cfg(not(feature = "link_lib3delight"))]
31mod dynamic;
32#[cfg(feature = "link_lib3delight")]
33mod linked;
34
35#[cfg(not(feature = "link_lib3delight"))]
36use self::dynamic as api;
37#[cfg(feature = "link_lib3delight")]
38use self::linked as api;
39
40// API initalization/on-demand loading of lib3delight -----------------
41
42#[cfg(not(feature = "manual_init"))]
43lazy_static::lazy_static! {
44    static ref NSI_API: api::ApiImpl =
45        api::ApiImpl::new().expect("Could not load lib3delight");
46}
47
48// Default modules ----------------------------------------------------
49
50#[macro_use]
51pub mod argument;
52pub use argument::*;
53
54// The canonical NSI trait, the Attribute<T> typed-name machinery, type
55// aliases (Point3F32 / Color3F32 / Matrix4F64 / …) and standard node-type
56// constants all live in `nsi-trait`. Re-export everything at this crate's
57// root so users can write `nsi_ffi_wrap::Nsi`, `nsi_ffi_wrap::Point3F32`,
58// `nsi_ffi_wrap::P`, etc. without depending on `nsi-trait` directly.
59pub use ::nsi_trait::*;
60
61pub mod c_adapter;
62pub use c_adapter::FfiApiAdapter;
63
64pub mod c_api;
65
66// Context should be in the crate root so we keep the module private.
67pub mod context;
68pub use context::*;
69
70#[cfg(feature = "output")]
71pub mod output;
72
73#[cfg(feature = "output")]
74pub use output::*;
75
76mod tests;
77
78#[macro_use]
79pub mod macros;
80
81/// Helper function to register output drivers for an API implementation.
82#[cfg(feature = "output")]
83pub fn register_output_drivers<A: FfiApi>(api: &A) {
84    // Register typed drivers for each pixel type
85    api.DspyRegisterDriver(
86        b"ferris_f32\0" as *const u8 as _,
87        Some(output::image_open::<f32>),
88        Some(output::image_write::<f32>),
89        Some(output::image_close::<f32>),
90        Some(output::image_query),
91    );
92    api.DspyRegisterDriver(
93        b"ferris_u32\0" as *const u8 as _,
94        Some(output::image_open::<u32>),
95        Some(output::image_write::<u32>),
96        Some(output::image_close::<u32>),
97        Some(output::image_query),
98    );
99    api.DspyRegisterDriver(
100        b"ferris_i32\0" as *const u8 as _,
101        Some(output::image_open::<i32>),
102        Some(output::image_write::<i32>),
103        Some(output::image_close::<i32>),
104        Some(output::image_query),
105    );
106    api.DspyRegisterDriver(
107        b"ferris_u16\0" as *const u8 as _,
108        Some(output::image_open::<u16>),
109        Some(output::image_write::<u16>),
110        Some(output::image_close::<u16>),
111        Some(output::image_query),
112    );
113    api.DspyRegisterDriver(
114        b"ferris_i16\0" as *const u8 as _,
115        Some(output::image_open::<i16>),
116        Some(output::image_write::<i16>),
117        Some(output::image_close::<i16>),
118        Some(output::image_query),
119    );
120    api.DspyRegisterDriver(
121        b"ferris_u8\0" as *const u8 as _,
122        Some(output::image_open::<u8>),
123        Some(output::image_write::<u8>),
124        Some(output::image_close::<u8>),
125        Some(output::image_query),
126    );
127    api.DspyRegisterDriver(
128        b"ferris_i8\0" as *const u8 as _,
129        Some(output::image_open::<i8>),
130        Some(output::image_write::<i8>),
131        Some(output::image_close::<i8>),
132        Some(output::image_query),
133    );
134}
135
136/// Trait abstracting the NSI C API functions.
137///
138/// This trait is implemented by both dynamic and linked API implementations,
139/// allowing the rest of the code to be generic over the loading mechanism.
140///
141/// Renderer implementations use this trait to provide the underlying C API
142/// functions, either through dynamic loading (dlopen) or static linking.
143pub trait FfiApi: Send + Sync {
144    fn NSIBegin(&self, nparams: c_int, params: *const NSIParam) -> NSIContext;
145    fn NSIEnd(&self, ctx: NSIContext);
146    fn NSICreate(
147        &self,
148        ctx: NSIContext,
149        handle: NSIHandle,
150        type_: *const c_char,
151        nparams: c_int,
152        params: *const NSIParam,
153    );
154    fn NSIDelete(
155        &self,
156        ctx: NSIContext,
157        handle: NSIHandle,
158        nparams: c_int,
159        params: *const NSIParam,
160    );
161    fn NSISetAttribute(
162        &self,
163        ctx: NSIContext,
164        object: NSIHandle,
165        nparams: c_int,
166        params: *const NSIParam,
167    );
168    fn NSISetAttributeAtTime(
169        &self,
170        ctx: NSIContext,
171        object: NSIHandle,
172        time: f64,
173        nparams: c_int,
174        params: *const NSIParam,
175    );
176    fn NSIDeleteAttribute(
177        &self,
178        ctx: NSIContext,
179        object: NSIHandle,
180        name: *const c_char,
181    );
182    #[allow(clippy::too_many_arguments)]
183    fn NSIConnect(
184        &self,
185        ctx: NSIContext,
186        from: NSIHandle,
187        from_attr: *const c_char,
188        to: NSIHandle,
189        to_attr: *const c_char,
190        nparams: c_int,
191        params: *const NSIParam,
192    );
193    fn NSIDisconnect(
194        &self,
195        ctx: NSIContext,
196        from: NSIHandle,
197        from_attr: *const c_char,
198        to: NSIHandle,
199        to_attr: *const c_char,
200    );
201    fn NSIEvaluate(
202        &self,
203        ctx: NSIContext,
204        nparams: c_int,
205        params: *const NSIParam,
206    );
207    fn NSIRenderControl(
208        &self,
209        ctx: NSIContext,
210        nparams: c_int,
211        params: *const NSIParam,
212    );
213
214    #[cfg(feature = "output")]
215    fn DspyRegisterDriver(
216        &self,
217        driver_name: *const c_char,
218        p_open: ndspy_sys::PtDspyOpenFuncPtr,
219        p_write: ndspy_sys::PtDspyWriteFuncPtr,
220        p_close: ndspy_sys::PtDspyCloseFuncPtr,
221        p_query: ndspy_sys::PtDspyQueryFuncPtr,
222    ) -> ndspy_sys::PtDspyError;
223}