1/*
2 This file contains the code required to load NSI at runtime instead of
3 linking with it at build time. To use, simply give an instance to the
4 context constructor:
5
6 NSI::DynamicAPI api;
7 NSI::Context ctx( api );
8
9 ctx.Begin();
10 ctx.Create( "myhandle", "mesh" );
11 ...
12
13 The DynamicAPI class loads and unloads the library so at least one instance
14 must be kept active while the renderer is in use.
15*/
16
17#ifndef __nsi_dynamic_hpp
18#define __nsi_dynamic_hpp
19
20#include "nsi.hpp"
21
22#if defined(__linux__) || defined(__APPLE__)
23# include <dlfcn.h>
24#elif defined(_WIN32)
25# include <windows.h>
26#endif
27
28#include <algorithm>
29#include <cstdlib>
30#include <string>
31
32namespace NSI
33{
34
35/* API provider which dynamically loads the renderer. */
36class DynamicAPI : public CAPI
37{
38#if defined(__linux__) || defined(__APPLE__)
39 void *m_lib;
40
41public:
42 template<typename T>
43 void LoadFunction( T &function, const char *name )
44 {
45 if( m_lib )
46 function = (T) dlsym( m_lib, name );
47 else
48 function = (T)0;
49 }
50#elif defined(_WIN32)
51 HMODULE m_lib;
52
53public:
54 template<typename T>
55 void LoadFunction( T &function, const char *name )
56 {
57 if( m_lib )
58 function = (T) GetProcAddress( m_lib, name );
59 else
60 function = (T)0;
61 }
62#else
63public:
64 template<typename T>
65 void LoadFunction( T &function, const char *name )
66 {
67 function = (T)0;
68 }
69#endif
70
71public:
72 DynamicAPI(const char* path = 0)
73 {
74#if defined(__linux__)
75 m_lib = dlopen( path ? path : "lib3delight.so", RTLD_NOW );
76#elif defined(__APPLE__)
77 if( path )
78 {
79 m_lib = dlopen( path, RTLD_NOW );
80 }
81 else
82 {
83 m_lib = dlopen( "/Applications/3Delight/lib/lib3delight.dylib", RTLD_NOW );
84 if( !m_lib )
85 {
86 m_lib = dlopen( "lib3delight.dylib", RTLD_NOW );
87 }
88 if( !m_lib )
89 {
90 /* Last resort, try DELIGHT. */
91 const char *delight = getenv("DELIGHT");
92 if( delight && delight[0] )
93 {
94 std::string dl = delight;
95 if( dl.back() != '/' )
96 dl.push_back('/');
97 dl.append("lib/lib3delight.dylib");
98 m_lib = dlopen(dl.c_str(), RTLD_NOW);
99 }
100 }
101 }
102#elif defined(_WIN32)
103 m_lib = LoadLibraryA( path ? path : "3Delight.dll" );
104 if( m_lib == NULL && !path )
105 {
106 /* PATH search might have been disabled by
107 SetDefaultDllDirectories(). Try with DELIGHT. */
108 const char *delight = getenv("DELIGHT");
109 if( delight && delight[0] )
110 {
111 std::string dl = delight;
112 std::replace(dl.begin(), dl.end(), '/', '\\');
113 if( dl.back() != '\\' )
114 dl.push_back('\\');
115 dl.append("bin\\3Delight.dll");
116 m_lib = LoadLibraryA(dl.c_str());
117 }
118 }
119#endif
120 LoadFunction( Begin, "NSIBegin" );
121 LoadFunction( End, "NSIEnd" );
122 LoadFunction( Create, "NSICreate" );
123 LoadFunction( Delete, "NSIDelete" );
124 LoadFunction( SetAttribute, "NSISetAttribute" );
125 LoadFunction( SetAttributeAtTime, "NSISetAttributeAtTime" );
126 LoadFunction( DeleteAttribute, "NSIDeleteAttribute" );
127 LoadFunction( Connect, "NSIConnect" );
128 LoadFunction( Disconnect, "NSIDisconnect" );
129 LoadFunction( Evaluate, "NSIEvaluate" );
130 LoadFunction( RenderControl, "NSIRenderControl" );
131 }
132
133 virtual ~DynamicAPI()
134 {
135#if defined(__linux__) || defined(__APPLE__)
136 if( m_lib != 0 )
137 dlclose( m_lib );
138#elif defined(_WIN32)
139 if( m_lib != 0 )
140 FreeLibrary( m_lib );
141#endif
142 }
143
144 virtual NSIContext_t NSIBegin(
145 int nparams,
146 const NSIParam_t *params ) const
147 {
148 if( Begin )
149 return Begin( nparams, params );
150 else
151 return NSI_BAD_CONTEXT;
152 }
153
154 virtual void NSIEnd(
155 NSIContext_t ctx ) const
156 {
157 if( End )
158 End( ctx );
159 }
160
161 virtual void NSICreate(
162 NSIContext_t ctx,
163 NSIHandle_t handle,
164 const char *type,
165 int nparams,
166 const NSIParam_t *params ) const
167 {
168 if( Create )
169 Create( ctx, handle, type, nparams, params );
170 }
171
172 virtual void NSIDelete(
173 NSIContext_t ctx,
174 NSIHandle_t handle,
175 int nparams,
176 const NSIParam_t *params ) const
177 {
178 if( Delete )
179 Delete( ctx, handle, nparams, params );
180 }
181
182 virtual void NSISetAttribute(
183 NSIContext_t ctx,
184 NSIHandle_t object,
185 int nparams,
186 const NSIParam_t *params ) const
187 {
188 if( SetAttribute )
189 SetAttribute( ctx, object, nparams, params );
190 }
191
192 virtual void NSISetAttributeAtTime(
193 NSIContext_t ctx,
194 NSIHandle_t object,
195 double time,
196 int nparams,
197 const NSIParam_t *params ) const
198 {
199 if( SetAttributeAtTime )
200 SetAttributeAtTime( ctx, object, time, nparams, params );
201 }
202
203 virtual void NSIDeleteAttribute(
204 NSIContext_t ctx,
205 NSIHandle_t object,
206 const char *name ) const
207 {
208 if( DeleteAttribute )
209 DeleteAttribute( ctx, object, name );
210 }
211
212 virtual void NSIConnect(
213 NSIContext_t ctx,
214 NSIHandle_t from,
215 const char *from_attr,
216 NSIHandle_t to,
217 const char *to_attr,
218 int nparams,
219 const NSIParam_t *params ) const
220 {
221 if( Connect )
222 Connect( ctx, from, from_attr, to, to_attr, nparams, params );
223 }
224
225 virtual void NSIDisconnect(
226 NSIContext_t ctx,
227 NSIHandle_t from,
228 const char *from_attr,
229 NSIHandle_t to,
230 const char *to_attr ) const
231 {
232 if( Disconnect )
233 Disconnect( ctx, from, from_attr, to, to_attr );
234 }
235
236 virtual void NSIEvaluate(
237 NSIContext_t ctx,
238 int nparams,
239 const NSIParam_t *params ) const
240 {
241 if( Evaluate )
242 Evaluate( ctx, nparams, params );
243 }
244
245 virtual void NSIRenderControl(
246 NSIContext_t ctx,
247 int nparams,
248 const NSIParam_t *params ) const
249 {
250 if( RenderControl )
251 RenderControl( ctx, nparams, params );
252 }
253
254private:
255 /* API function pointers. */
256 NSIContext_t (*Begin)(
257 int nparams,
258 const NSIParam_t *params );
259
260 void (*End)(
261 NSIContext_t ctx );
262
263 void (*Create)(
264 NSIContext_t ctx,
265 NSIHandle_t handle,
266 const char *type,
267 int nparams,
268 const NSIParam_t *params );
269
270 void (*Delete)(
271 NSIContext_t ctx,
272 NSIHandle_t handle,
273 int nparams,
274 const NSIParam_t *params );
275
276 void (*SetAttribute)(
277 NSIContext_t ctx,
278 NSIHandle_t object,
279 int nparams,
280 const NSIParam_t *params );
281
282 void (*SetAttributeAtTime)(
283 NSIContext_t ctx,
284 NSIHandle_t object,
285 double time,
286 int nparams,
287 const NSIParam_t *params );
288
289 void (*DeleteAttribute)(
290 NSIContext_t ctx,
291 NSIHandle_t object,
292 const char *name );
293
294 void (*Connect)(
295 NSIContext_t ctx,
296 NSIHandle_t from,
297 const char *from_attr,
298 NSIHandle_t to,
299 const char *to_attr,
300 int nparams,
301 const NSIParam_t *params );
302
303 void (*Disconnect)(
304 NSIContext_t ctx,
305 NSIHandle_t from,
306 const char *from_attr,
307 NSIHandle_t to,
308 const char *to_attr );
309
310 void (*Evaluate)(
311 NSIContext_t ctx,
312 int nparams,
313 const NSIParam_t *params );
314
315 void (*RenderControl)(
316 NSIContext_t ctx,
317 int nparams,
318 const NSIParam_t *params );
319};
320
321}
322
323#endif