~ubuntu-branches/debian/sid/ember/sid

« back to all changes in this revision

Viewing changes to src/components/lua/luaobject.h

  • Committer: Bazaar Package Importer
  • Author(s): Michael Koch
  • Date: 2009-10-22 23:21:17 UTC
  • mfrom: (1.1.1 upstream) (2.1.1 sid)
  • Revision ID: james.westby@ubuntu.com-20091022232117-isr8u3402qmu7ilo
Tags: 0.5.7-1
* New upstream release.
  - Compile against current ogre (Closes: #551431)
  - Removed debian/patches/ember-gcc4.4.patch. Merged upstream.
  - Updated Depends on ember-media.
* Add libboost-thread-dev tp Build-Depends.
* Make debian/rules independent from upstream version.
* Updated watch file to allow automatic download of new upstream
  tarballs.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// luaobject.h
 
2
//
 
3
// Copyright 2008 by Nigel Atkinson suprapilot+LuaCode@gmail.com 
 
4
//
 
5
//    This library is free software: you can redistribute it and/or modify
 
6
//    it under the terms of the GNU Lesser General Public License as published by
 
7
//    the Free Software Foundation, either version 3 of the License, or
 
8
//    (at your option) any later version.
 
9
//
 
10
//    This library is distributed in the hope that it will be useful,
 
11
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
//    GNU Lesser General Public License for more details.
 
14
//
 
15
//    A copy of theGNU General Public License is availible at:
 
16
//    <http://www.gnu.org/licenses/>.
 
17
// 
 
18
// Makes interfacing with Lua easier.  
 
19
// Tested with Lua 5.1.3 and 5.1.2.
 
20
// MSVC 7.12 (2003) and GCC (g++) 4.1.2
 
21
 
 
22
// 8th May 2008 Nigel
 
23
// Added LuaException class and changed all throws to use it.  User code can use it too.
 
24
// It grabs any string, if any, from the top of the Lua stack.
 
25
 
 
26
 
 
27
#ifndef __LUAOBJECT_H
 
28
#define __LUAOBJECT_H
 
29
 
 
30
extern "C" {
 
31
#include "lua.h"
 
32
#include "lualib.h"
 
33
#include "lauxlib.h"
 
34
}
 
35
//#include <lua.hpp>
 
36
#include <string>
 
37
#include <sstream>
 
38
 
 
39
// Used when the object to set the LuaRef to, on creation, is on the top of the lua stack.
 
40
struct fromStack
 
41
{
 
42
        lua_State *mL;
 
43
 
 
44
        fromStack( lua_State *L ) : mL(L)
 
45
        {;}
 
46
};
 
47
 
 
48
// Pops a number of objects off the Lua stack once out of scope.
 
49
// Used to ensure the stack is left as it was, even if exceptions occur.
 
50
class luaPop
 
51
{
 
52
        lua_State *mL;
 
53
        int mNum;
 
54
 
 
55
public:
 
56
 
 
57
        luaPop( lua_State *L, int num=1 ): mL(L), mNum(num)
 
58
        {;}
 
59
 
 
60
        ~luaPop()
 
61
        {
 
62
                lua_pop( mL, mNum );
 
63
        }
 
64
};
 
65
 
 
66
class LuaRef;
 
67
 
 
68
// Basic "ANY" class for representing Lua objects.
 
69
// Used in calling Lua functions as parameters.
 
70
class LuaVal
 
71
{
 
72
        int mType;
 
73
        double d;
 
74
        std::string str;
 
75
        lua_CFunction func;
 
76
        LuaRef *obj;
 
77
 
 
78
public:
 
79
        LuaVal() : mType( LUA_TNIL ), obj(NULL)
 
80
        {;}
 
81
 
 
82
        LuaVal( double n ) : mType( LUA_TNUMBER ), d( n ), obj(NULL)
 
83
        {;}
 
84
 
 
85
        LuaVal( const std::string& n ) : mType( LUA_TSTRING ), str( n ), obj(NULL)
 
86
        {;}
 
87
 
 
88
        LuaVal( const char *n ) : mType( LUA_TSTRING ), str( n ), obj(NULL)
 
89
        {;}
 
90
 
 
91
        LuaVal( lua_CFunction n ) : mType( LUA_TFUNCTION ), func( n ), obj(NULL)
 
92
        {;}
 
93
 
 
94
        LuaVal( LuaRef *o ) : mType( LUA_TLIGHTUSERDATA ), obj(o)
 
95
        {;}
 
96
 
 
97
        void push( lua_State *L );
 
98
};
 
99
 
 
100
 
 
101
// Exception class
 
102
class LuaException
 
103
{
 
104
        std::string error;
 
105
        std::string luaError;
 
106
        std::string file;
 
107
        long line;
 
108
        lua_State *mL;
 
109
 
 
110
        // Do we we need a copy constuctor? I think the default supplied one works.
 
111
 
 
112
public:
 
113
        LuaException( lua_State *L, const char *str, const char *filename, long fileline ) : error(str), file(filename), line(fileline)
 
114
        {
 
115
                if( lua_gettop( L ) != 0 )
 
116
                        if( lua_isstring( L, -1 ) )
 
117
                                luaError = lua_tostring( L, -1 );
 
118
                mL = L;
 
119
        }
 
120
 
 
121
        const std::string& getError() { return error; }
 
122
        const std::string& getLuaError() { return luaError; }
 
123
        lua_State *getLuaState() { return mL; }
 
124
        std::string getErrorForDisplay()
 
125
        {
 
126
                std::stringstream ss;
 
127
 
 
128
                ss << "*** " << error << " ***" << std::endl; 
 
129
                ss << "*** " << luaError << " ***" << std::endl;
 
130
                ss << "*** In file: " << file << " Line: " << line << " ***" << std::endl;
 
131
 
 
132
                return ss.str();
 
133
        }
 
134
 
 
135
        ~LuaException() throw () {}
 
136
};
 
137
 
 
138
// A Lua Object.  Represents a Lua object within a Lua state.
 
139
// Each is referenced, so the Lua GC will not garbage collect this object while this instance is in scope.
 
140
// Once out of scope, the Lua object could be garbage collected, depending on any other references.
 
141
class LuaRef
 
142
{
 
143
        int mRef;                       // Index to reference of object.
 
144
        lua_State *mL;          // and the vm
 
145
 
 
146
        // Private internal class for returning as a proxy object.  This is used when asked for a table element.
 
147
        // This class can not be instantated outside of LuaRef.  It lets you use syntax like the following:
 
148
        // 
 
149
        // tbl["index"] = something;
 
150
        //
 
151
        // given that "tbl" is a LuaRef.
 
152
        
 
153
        class tableElement
 
154
        {
 
155
                // Allow outside class access to members, and private constructor.
 
156
                friend class LuaRef;
 
157
                
 
158
                std::string mKey;               // Element index
 
159
                int mRef;                       // Reference to table
 
160
                lua_State *mL;
 
161
        
 
162
                // Private constructor.  
 
163
                tableElement( lua_State *L, int ref, const char *key ) : mKey(key), mRef( ref ), mL(L)
 
164
                { ; }
 
165
 
 
166
        public:
 
167
 
 
168
                // Put table element on top of Lua stack.
 
169
                void push()
 
170
                {
 
171
                        lua_rawgeti( mL, LUA_REGISTRYINDEX, mRef );
 
172
                        lua_getfield( mL, -1, mKey.c_str() );
 
173
                }
 
174
 
 
175
                // Return the 'type' of the table element.
 
176
                int type()
 
177
                {
 
178
                        int ret;
 
179
 
 
180
                        push();
 
181
                        ret =  lua_type( mL, -1 );
 
182
                        lua_pop( mL, 2 );                       // Remove index and table from stack.
 
183
 
 
184
                        return ret;
 
185
                }
 
186
 
 
187
                double operator = ( double f )
 
188
                {
 
189
                        luaPop p(mL);
 
190
                        lua_rawgeti( mL, LUA_REGISTRYINDEX, mRef );
 
191
                        lua_pushnumber( mL, f );
 
192
                        lua_setfield( mL, -2, mKey.c_str() );
 
193
 
 
194
                        return f;
 
195
                }
 
196
 
 
197
                std::string & operator = ( std::string & str )
 
198
                {
 
199
                        operator = ( str.c_str() );                     // Just re-use the const char * code.
 
200
 
 
201
                        return str;
 
202
                }
 
203
 
 
204
                const char * operator = ( const char *str )
 
205
                {
 
206
                        luaPop p(mL);
 
207
                        lua_rawgeti( mL, LUA_REGISTRYINDEX, mRef );
 
208
                        lua_pushstring( mL, str );
 
209
                        lua_setfield( mL, -2, mKey.c_str() );
 
210
 
 
211
                        return str;
 
212
                }
 
213
 
 
214
                lua_CFunction operator = ( lua_CFunction func )
 
215
                {
 
216
                        luaPop p(mL);
 
217
                        lua_rawgeti( mL, LUA_REGISTRYINDEX, mRef );
 
218
                        lua_pushcfunction( mL, func );
 
219
                        lua_setfield( mL, -2, mKey.c_str() );
 
220
 
 
221
                        return func;
 
222
                }
 
223
 
 
224
                LuaRef & operator = ( LuaRef &obj )
 
225
                {
 
226
                        luaPop p(mL);
 
227
 
 
228
                        lua_rawgeti( mL, LUA_REGISTRYINDEX, mRef );
 
229
                        obj.push();
 
230
                        lua_setfield( mL, -2, mKey.c_str() );
 
231
 
 
232
                        return obj;
 
233
                }
 
234
 
 
235
                operator double()
 
236
                {
 
237
                        luaPop p1(mL,2);                // Removes index and table from Lua stack once out of scope.
 
238
 
 
239
                        push(); 
 
240
                        
 
241
                        return lua_tonumber( mL, -1 );
 
242
                }
 
243
 
 
244
                operator std::string()
 
245
                {
 
246
                        push(); 
 
247
                        std::string str( lua_tostring( mL, -1 ) );
 
248
                        lua_pop( mL, 2 );               // Removes index and table from Lua stack
 
249
                                
 
250
                        return str;
 
251
                }
 
252
 
 
253
                operator LuaRef()
 
254
                {
 
255
                        luaPop p( mL, 2);
 
256
                        
 
257
                        push();
 
258
                        fromStack fs( mL );
 
259
                                                
 
260
                        return LuaRef(fs);
 
261
                }
 
262
        };
 
263
 
 
264
public:
 
265
 
 
266
        LuaRef( lua_State *L ) : mRef( LUA_NOREF ), mL( L )                     // For "new" objects, that will be assigned a value later.
 
267
        {;}
 
268
 
 
269
        LuaRef( lua_State *L, const char *name ) : mL( L )                      // Reference an existing object.  Note that numbers and strings
 
270
        {                                                                                                                       // will be copied.  Any changes will not change the original.
 
271
                lua_getglobal( mL, name );
 
272
                mRef = luaL_ref( mL, LUA_REGISTRYINDEX );
 
273
        }
 
274
 
 
275
        LuaRef( fromStack fs ) : mL( fs.mL )                                            // Reference an existing object that is on top of the Lua stack.
 
276
        {                                                                                                                       // Note same cavet as above.
 
277
                mRef = luaL_ref( mL, LUA_REGISTRYINDEX );                               // Removes from stack.
 
278
        }
 
279
 
 
280
        LuaRef( tableElement & te ) : mL( te.mL )                                       // Reference a table element.
 
281
        {
 
282
                lua_rawgeti( te.mL, LUA_REGISTRYINDEX, te.mRef );
 
283
                lua_getfield( te.mL, -1, te.mKey.c_str() );
 
284
                mRef = luaL_ref( mL, LUA_REGISTRYINDEX );
 
285
        }
 
286
 
 
287
        LuaRef(const LuaRef &obj ) : mL( obj.mL )
 
288
        {
 
289
                LuaRef& objRef = const_cast<LuaRef&>(obj);
 
290
                objRef.push();
 
291
                mRef = luaL_ref( mL, LUA_REGISTRYINDEX );
 
292
        }
 
293
 
 
294
        ~LuaRef()                                                                                                       // We're gone.  Release reference to object.
 
295
        {
 
296
                luaL_unref( mL, LUA_REGISTRYINDEX, mRef );
 
297
        }
 
298
 
 
299
        // Place object on top of Lua stack.
 
300
        void push()
 
301
        {
 
302
                lua_rawgeti( mL, LUA_REGISTRYINDEX, mRef );
 
303
        }
 
304
 
 
305
        // Return the 'type' of the object
 
306
        int type()
 
307
        {
 
308
                int ret;
 
309
 
 
310
                push();
 
311
                ret =  lua_type( mL, -1 );
 
312
                lua_pop( mL, 1 );
 
313
 
 
314
                return ret;
 
315
        }
 
316
 
 
317
        // Create a new table.
 
318
        void createTable()
 
319
        {
 
320
                lua_newtable( mL );
 
321
                mRef = luaL_ref( mL, LUA_REGISTRYINDEX );
 
322
        }
 
323
 
 
324
        // Create a new table and associate a global variable with it.
 
325
        void createTable( const char *name )
 
326
        {
 
327
                createTable();
 
328
                store( name );
 
329
        }
 
330
 
 
331
        // Return a proxy to a table element givin an index.
 
332
        tableElement operator [] ( const char *key )
 
333
        {
 
334
                push();
 
335
 
 
336
                if( ! lua_istable( mL, -1 ) )
 
337
                        throw LuaException( mL, "LuaRef operator [] used on a non Lua table", __FILE__, __LINE__ );
 
338
 
 
339
                lua_pop( mL, 1 );
 
340
 
 
341
                return tableElement( mL, mRef, key );
 
342
        }
 
343
 
 
344
        // Return a proxy to a table element givin an index.
 
345
        tableElement operator [] ( int key )
 
346
        {
 
347
                push();
 
348
 
 
349
                if( ! lua_istable( mL, -1 ) )
 
350
                        throw LuaException( mL, "LuaRef operator [] used on a non Lua table", __FILE__, __LINE__ );
 
351
 
 
352
                lua_pop( mL, 1 );
 
353
 
 
354
                std::stringstream ss;
 
355
 
 
356
                ss << key;
 
357
 
 
358
                return tableElement( mL, mRef, ss.str().c_str() );
 
359
        }
 
360
 
 
361
        // Reference an object referenced by "obj"
 
362
        LuaRef & operator = ( LuaRef &obj )
 
363
        {
 
364
                luaL_unref( mL, LUA_REGISTRYINDEX, mRef );
 
365
                mL = obj.mL;
 
366
                obj.push();
 
367
                mRef = luaL_ref( mL, LUA_REGISTRYINDEX );
 
368
 
 
369
                return *this;
 
370
        }
 
371
 
 
372
        // Reference a number as a new object.
 
373
        double operator = ( double f )
 
374
        {
 
375
                luaL_unref( mL, LUA_REGISTRYINDEX, mRef );
 
376
                lua_pushnumber( mL, f );
 
377
                mRef = luaL_ref( mL, LUA_REGISTRYINDEX );
 
378
                return f;
 
379
        }
 
380
 
 
381
        // Reference a string as a new object.
 
382
        std::string & operator = ( std::string & str )
 
383
        {
 
384
                operator = ( str.c_str() );
 
385
                return str;
 
386
        }
 
387
 
 
388
        // Reference a string.
 
389
        const char * operator = ( const char *str )
 
390
        {
 
391
                luaL_unref( mL, LUA_REGISTRYINDEX, mRef );
 
392
                
 
393
                lua_pushstring( mL, str );
 
394
                mRef = luaL_ref( mL, LUA_REGISTRYINDEX );               
 
395
                return str;
 
396
        }
 
397
 
 
398
        // Reference a function.
 
399
        lua_CFunction operator = ( lua_CFunction func )
 
400
        {
 
401
                luaL_unref( mL, LUA_REGISTRYINDEX, mRef );
 
402
                lua_pushcfunction( mL, func );
 
403
                mRef = luaL_ref( mL, LUA_REGISTRYINDEX );
 
404
                return func;
 
405
        }
 
406
 
 
407
        // Associate referenced object with a name, or global variable.
 
408
        void store( const char *name )
 
409
        {
 
410
                push();         
 
411
                lua_setglobal( mL, name);
 
412
        }
 
413
 
 
414
        // Associate referenced object as a member of a table.
 
415
        void store( const char *name, LuaRef & table )
 
416
        {
 
417
                if( table.type() != LUA_TTABLE )
 
418
                        throw LuaException( mL, "given object is not a table.", __FILE__, __LINE__ );
 
419
 
 
420
                table.push();
 
421
                push();
 
422
                lua_setfield( mL, -2, name );   // Pops value
 
423
                lua_pop( mL, 1 );       // Pops table
 
424
        }
 
425
 
 
426
        // Return as a number.
 
427
        operator double()
 
428
        {
 
429
                double ret = 0.0;
 
430
                luaPop p(mL);
 
431
                push();
 
432
 
 
433
                if( lua_isnumber( mL, -1 ) )
 
434
                        ret = lua_tonumber( mL, -1 );
 
435
                else
 
436
                        throw LuaException( mL, "LuaRef referenced object is not a number.", __FILE__, __LINE__ );
 
437
 
 
438
                return ret;
 
439
        }
 
440
 
 
441
        // Return as a string
 
442
        operator std::string()
 
443
        {
 
444
                std::string ret;
 
445
                luaPop p(mL);
 
446
                
 
447
                push();
 
448
 
 
449
                if( lua_isstring( mL, -1 ) )
 
450
                        ret = lua_tostring( mL, -1 );
 
451
                else
 
452
                        throw LuaException( mL, "LuaRef referenced object is not a string.", __FILE__, __LINE__ );
 
453
 
 
454
                return ret;
 
455
        }
 
456
 
 
457
        // Return as an object
 
458
        template<typename Treturn>
 
459
        Treturn asObject(const char* className)
 
460
        {
 
461
                luaPop p(mL);
 
462
 
 
463
                push();
 
464
 
 
465
                Treturn* ptrObj = * static_cast<Treturn**>(luaL_checkudata(mL, -1, className));
 
466
                return *ptrObj;
 
467
        }
 
468
 
 
469
        // Return as an object
 
470
        template<typename Treturn>
 
471
        Treturn asObject(const std::string& className)
 
472
        {
 
473
                return asObject<Treturn>(className.c_str());
 
474
        }
 
475
 
 
476
        // The next few overloads of operator () allow calling a referenced Lua object (provided its a function),
 
477
        // with the same syntax as calling a C++ function.  Only the types LuaVal has conversions for can be used.
 
478
        // Upto 4 parameters, but more can be added.  Returns true on succesfull call.  No results are returned.
 
479
 
 
480
        LuaRef operator () ()
 
481
        {
 
482
                push();
 
483
 
 
484
                if( lua_isfunction( mL, -1 ) )
 
485
                {
 
486
                        if( lua_pcall( mL, 0, 1, 0 ) != 0 )
 
487
                                throw LuaException( mL, "Error running function in LuaRef operator ()", __FILE__, __LINE__ );
 
488
                }
 
489
                else
 
490
                {
 
491
            lua_pop( mL, 1 );
 
492
                        throw LuaException( mL, "LuaRef operator () called but does not reference a function", __FILE__, __LINE__ );
 
493
                }
 
494
                
 
495
                fromStack fs( mL );
 
496
 
 
497
                return LuaRef( fs );
 
498
        }
 
499
 
 
500
        LuaRef operator () ( LuaVal p1 )
 
501
        {
 
502
                push();
 
503
 
 
504
                if( lua_isfunction( mL, -1 ) )
 
505
                {
 
506
                        p1.push(mL);
 
507
                        
 
508
                        if( lua_pcall( mL, 1, 1, 0 ) != 0 )
 
509
                                throw LuaException( mL, "Error running function in LuaRef operator ()", __FILE__, __LINE__ );
 
510
                }
 
511
                else
 
512
                {
 
513
            lua_pop( mL, 1 );
 
514
                        throw LuaException( mL, "LuaRef operator () called but does not reference a function", __FILE__, __LINE__ );
 
515
                }
 
516
                
 
517
                fromStack fs( mL );
 
518
 
 
519
                return LuaRef( fs );
 
520
        }
 
521
 
 
522
        LuaRef operator () ( LuaVal p1, LuaVal p2 )
 
523
        {
 
524
                push();
 
525
 
 
526
                if( lua_isfunction( mL, -1 ) )
 
527
                {
 
528
                        p1.push(mL);
 
529
                        p2.push(mL);
 
530
                        
 
531
                        if( lua_pcall( mL, 2, 1, 0 ) != 0 )
 
532
                                throw LuaException( mL, "Error running function in LuaRef operator ()", __FILE__, __LINE__ );
 
533
                }
 
534
                else
 
535
                {
 
536
            lua_pop( mL, 1 );
 
537
                        throw LuaException( mL, "LuaRef operator () called but does not reference a function", __FILE__, __LINE__ );
 
538
                }
 
539
                
 
540
                fromStack fs( mL );
 
541
 
 
542
                return LuaRef( fs );
 
543
        }
 
544
 
 
545
        LuaRef operator () ( LuaVal p1, LuaVal p2, LuaVal p3 )
 
546
        {
 
547
                push();
 
548
 
 
549
                if( lua_isfunction( mL, -1 ) )
 
550
                {
 
551
                        p1.push(mL);
 
552
                        p2.push(mL);
 
553
                        p3.push(mL);
 
554
                        
 
555
                        if( lua_pcall( mL, 3, 1, 0 ) != 0 )
 
556
                                throw LuaException( mL,"Error running function in LuaRef operator ()" , __FILE__, __LINE__ );
 
557
                }
 
558
                else
 
559
                {
 
560
            lua_pop( mL, 1 );
 
561
                        throw LuaException( mL, "LuaRef operator () called but does not reference a function", __FILE__, __LINE__ );
 
562
                }
 
563
                
 
564
                fromStack fs( mL );
 
565
 
 
566
                return LuaRef( fs );
 
567
        }
 
568
 
 
569
        LuaRef operator () ( LuaVal p1, LuaVal p2, LuaVal p3, LuaVal p4 )
 
570
        {
 
571
                push();
 
572
 
 
573
                if( lua_isfunction( mL, -1 ) )
 
574
                {
 
575
                        p1.push(mL);
 
576
                        p2.push(mL);
 
577
                        p3.push(mL);
 
578
                        p4.push(mL);
 
579
                        
 
580
                        if( lua_pcall( mL, 4, 1, 0 ) != 0 )
 
581
                                throw LuaException( mL, "Error running function in LuaRef operator ()", __FILE__, __LINE__ );
 
582
                }
 
583
                else
 
584
                {
 
585
            lua_pop( mL, 1 );
 
586
                        throw LuaException( mL,"LuaRef operator () called but does not reference a function" , __FILE__, __LINE__ );
 
587
                }
 
588
                
 
589
                fromStack fs( mL );
 
590
 
 
591
                return LuaRef( fs );
 
592
        }
 
593
};
 
594
 
 
595
 
 
596
 
 
597
#endif // __LUAOBJECT_H