nsi_dynamic.hpp

  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