Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 330 lines (282 sloc) 12.218 kb
08e2c81b »
2011-03-18 lua object wrapper baseclass
1 #ifndef _LUAOBJECT_H
2 #define _LUAOBJECT_H
3
78ad0904 »
2011-03-18 hacking in a register func based on Matrix_register. I haven't though…
4 #include "LuaManager.h"
aea91939 »
2011-03-21 if you want to go to lua you gotta tell me when you're about to die
5 #include "DeleteEmitter.h"
054d9b45 »
2011-04-12 move the acquire/release stuff into a seperate class so that starsyst…
6
77df8e3a »
2011-03-23 look at me, documenting stuff
7 //
8 // LuaObject provides proxy objects and tracking facilities to safely get
9 // objects in and out of lua. the basic idea is that for every class you want
5cabc0d5 »
2011-03-27 rename the object classes a bit
10 // to expose to lua, you define LuaObject wrapper class that defines the
77df8e3a »
2011-03-23 look at me, documenting stuff
11 // lua name lua name, methods and metamethods for that class. you then call
12 // methods on this class to push and pull objects to and from the lua stack
13 //
14 //
15 // if you just want to use it, do something like:
16 //
17 // push a value onto the lua stack before method call or return (you (c++)
18 // remains responsible for deallocating the object)
19 //
20 // Ship *s = new Ship("Eagle Long Range Fighter");
21 // LuaShip::PushToLua(s);
22 //
23 // push a value onto the lua stack (lua will deallocate the object when it
24 // goes out of scope and the garbage collector runs. OBJECT MUST BE
25 // HEAP-ALLOCATED)
26 //
27 // Ship *s = new Ship("Eagle Long Range Fighter");
28 // LuaShip::PushToLuaGC(s);
29 //
9d6dcc6f »
2011-03-28 change pullfromlua to getfromlua so that type exceptions show the cor…
30 // get a value from the lua stack at index n (causes lua exception if the
31 // object doesn't exist or the types don't match)
77df8e3a »
2011-03-23 look at me, documenting stuff
32 //
9d6dcc6f »
2011-03-28 change pullfromlua to getfromlua so that type exceptions show the cor…
33 // Ship *s = LuaShip::GetFromLua(1);
77df8e3a »
2011-03-23 look at me, documenting stuff
34 //
35 // note that it uses the singleton lua state provided by LuaManager. there's
36 // no facility to use a different lua state. if you think you need to you're
37 // probably doing something wrong. ask the devs if you're not sure.
38 //
39 //
40 // if you need to expose a new class to lua, do this (using Ship/LuaShip as an
41 // example)
42 //
43 // - have your class inherit from DeleteEmitter
44 //
5cabc0d5 »
2011-03-27 rename the object classes a bit
45 // - add a typedef for the wrapper class to the bottom of LuaObjectBase.h:
7cef0470 »
2011-03-23 template the uncopyable stuff
46 //
77df8e3a »
2011-03-23 look at me, documenting stuff
47 // class Ship;
5cabc0d5 »
2011-03-27 rename the object classes a bit
48 // typedef LuaObject<Ship> LuaShip;
77df8e3a »
2011-03-23 look at me, documenting stuff
49 //
7cef0470 »
2011-03-23 template the uncopyable stuff
50 // OR if your class can't inherit from DeleteEmitter for some reason, use
51 // this kind of typedef instead to create a subclass
52 //
f850e72c »
2011-06-27 fix up parts of the StarSystem interface. now only uses SystemPath fo…
53 // class SystemPath;
54 // typedef LuaObjectUncopyable<SystemPath,LuaUncopyable<SystemPath> > LuaSystemPath;
b10fb055 »
2011-03-24 fix the comments to make it clearer that LuaUncopyable wrapped classe…
55 //
56 // you probably don't want to do this unless you understand the entire
5cabc0d5 »
2011-03-27 rename the object classes a bit
57 // LuaObjectBase system. read on and ask for help :)
7cef0470 »
2011-03-23 template the uncopyable stuff
58 //
77df8e3a »
2011-03-23 look at me, documenting stuff
59 // - arrange for the wrapper class RegisterClass() method to be called in
60 // LuaManager::Init in LuaManager.cpp
7cef0470 »
2011-03-23 template the uncopyable stuff
61 //
77df8e3a »
2011-03-23 look at me, documenting stuff
62 // LuaShip::RegisterClass();
63 //
64 // - make a new file LuaShip.cpp with static data for the lua class name and
65 // method/metamethod pointer tables (copy from one of the others to get the
66 // idea)
67 //
68 // - add the new file to the build system
69 //
70 // - implement your lua methods in that file
71 //
72 //
73 // if you want to understand how this works, read on :)
74 //
75 // the basic premise of all this is that lua never holds a pointer to the c++
76 // object. instead, when a c++ object is pushed to the lua stack a lua object
77 // (that is, a value with a metatable) is created that internally has a
78 // numeric identifier. the original object is added to a hashtable (the
79 // registry) with the identifier as the key. when lua calls a method against
80 // the object, the appropriate method/metamethod is called with the lua object
81 // on the stack. the method implementation (c++) then pulls these objects from
82 // the stack via wrapper classes that handle the details of looking up the
83 // real object in the registry
84 //
05cf9f44 »
2011-04-05 track existing userdata in lua and reuse if the same pointer is pushe…
85 // a object pointer (lightuserdata) -> userdata mapping is held in the lua
86 // registry. when a value is pushed this is consulted first. if lua already
87 // knows about the object the userdata is reused. this ensures that objects
88 // that only exist once outside lua also only exist once inside lua, and means
89 // that object equality works as expected. these mapping holds weak references
90 // so that the operation of the garbage collector is not affected
91 //
77df8e3a »
2011-03-23 look at me, documenting stuff
92 // objects are removed from the registry when either the c++ or the lua side
93 // releases them. on the lua side this is handled by the __gc metamethod. on
94 // the c++ side this is done via the DeleteEmitter class that all wrapped
95 // classes are expected to inherit from. a callback is add to the onDelete
96 // signal when the object is registered. when either of these things are
97 // called the object is removed from the registry. the callback will also
98 // delete the object if it was pushed with PushToLuaGC to indicate that lua
99 // owns the object
100 //
101
102 // type for internal object identifiers
74637415 »
2011-04-29 use a regular int for the lua object id, and remove the need for stdint
103 typedef unsigned int lid;
01093ce4 »
2011-03-20 use a uintptr since lightuserdata is a void pointer make a typedef
104
2f40746f »
2011-04-19 lua type promotions. the idea is that you can pass the player to some…
105 // type for promotion test callbacks
106 typedef bool (*PromotionTest)(DeleteEmitter *o);
107
1789f632 »
2011-03-31 let LuaSerializer get at the objects inside
108 // the base class for wrapper classes. it has no public interface. everything
109 // you need goes through the wrapper classes
5cabc0d5 »
2011-03-27 rename the object classes a bit
110 class LuaObjectBase {
1789f632 »
2011-03-31 let LuaSerializer get at the objects inside
111 friend class LuaSerializer;
188123f0 »
2011-03-30 actually expose the wrapper innards, and also add a inheritance check…
112
dbcf1397 »
2012-06-19 method to create typeless lua objects (plain tables with methods/meta…
113 public:
114 // creates a single "typeless" object and attaches the listed methods,
115 // attributes and metamethods to it. leaves the created object on the
116 // stack
117 static void CreateObject(const luaL_Reg *methods, const luaL_Reg *attrs, const luaL_Reg *meta);
118
fec5b1ef »
2011-03-23 push to lua stack on creation, don't return, remove public interface.…
119 protected:
12ffbe2a »
2011-04-12 doc update and some reshuffling
120 // base class constructor, called by the wrapper Push* methods
77686229 »
2011-04-11 a hack job to get a working specialization for LuaObject<StarSystem> …
121 LuaObjectBase(DeleteEmitter *o, const char *type) : m_object(o), m_type(type) {};
5cabc0d5 »
2011-03-27 rename the object classes a bit
122 virtual ~LuaObjectBase() {}
c6beeaf7 »
2011-03-21 rework as true wrappers rather than just type magic things. still war…
123
77df8e3a »
2011-03-23 look at me, documenting stuff
124 // creates a class in the lua vm with the given name and attaches the
825221c6 »
2011-05-03 remove the "magic" index in favour of an explicit attribute table. th…
125 // listed methods to it and the listed metamethods to its metaclass. if
126 // attributes extra magic is added to the metaclass to make them work as
127 // expected
c97ab3aa »
2012-05-06 global rename luaL_reg (which no longer exists) to luaL_Reg
128 static void CreateClass(const char *type, const char *parent, const luaL_Reg *methods, const luaL_Reg *attrs, const luaL_Reg *meta);
b8db5b1a »
2011-03-20 use lightuserdata to store the ids
129
12ffbe2a »
2011-04-12 doc update and some reshuffling
130 // push an already-registered object onto the lua stack. the object is
131 // looked up in the lua registry, if it exists a copy of its userdata is
132 // placed on the lua stack. returns true if the object exist and was
133 // pushed, false otherwise
ae6776e1 »
2011-04-10 have the wrapper class create the object wrapper so that it has the r…
134 static bool PushRegistered(DeleteEmitter *o);
12ffbe2a »
2011-04-12 doc update and some reshuffling
135
136 // pushes the raw object into lua. new userdata is create and stored in
137 // the lookup table in the lua registry for PushRegistered to user later,
138 // and then is added to the stack. if wantdelete is true, lua takes
139 // control of the object and will call delete on it when it is finished
140 // with it
77686229 »
2011-04-11 a hack job to get a working specialization for LuaObject<StarSystem> …
141 static void Push(LuaObjectBase *lo, bool wantdelete);
05cf9f44 »
2011-04-05 track existing userdata in lua and reuse if the same pointer is pushe…
142
77df8e3a »
2011-03-23 look at me, documenting stuff
143 // pulls an object off the lua stack and returns its associated c++
12ffbe2a »
2011-04-12 doc update and some reshuffling
144 // object. type is the lua type string of the object. a lua exception is
145 // triggered if the object on the stack is not of this type
146 static DeleteEmitter *GetFromLua(int index, const char *type);
77686229 »
2011-04-11 a hack job to get a working specialization for LuaObject<StarSystem> …
147
9f297b0b »
2011-04-12 checkfromlua to complement getfromlua
148 // does exactly the same as GetFromLua without triggering exceptions
149 static DeleteEmitter *CheckFromLua(int index, const char *type);
150
2f40746f »
2011-04-19 lua type promotions. the idea is that you can pass the player to some…
151 // register a promotion test. when an object with lua type base_type is
152 // pushed, test_fn will be called. if it returns true then the created lua
153 // object will be of target_type
afb5f006 »
2011-04-19 remove promotion debug; rename promotion register method
154 static void RegisterPromotion(const char *base_type, const char *target_type, PromotionTest test_fn);
2f40746f »
2011-04-19 lua type promotions. the idea is that you can pass the player to some…
155
12ffbe2a »
2011-04-12 doc update and some reshuffling
156 // abstract functions for the object acquire/release functions. these are
157 // called to somehow record that the object is "in use". the wrapper class
158 // handles the hard details of this (most of the time it results in a noop)
054d9b45 »
2011-04-12 move the acquire/release stuff into a seperate class so that starsyst…
159 virtual void Acquire(DeleteEmitter *) = 0;
160 virtual void Release(DeleteEmitter *) = 0;
161
95d668b4 »
2011-03-30 expose some of the object wrapper innards for the serializer
162 private:
05cf9f44 »
2011-04-05 track existing userdata in lua and reuse if the same pointer is pushe…
163 LuaObjectBase() {}
95d668b4 »
2011-03-30 expose some of the object wrapper innards for the serializer
164 LuaObjectBase(const LuaObjectBase &) {}
165
fec5b1ef »
2011-03-23 push to lua stack on creation, don't return, remove public interface.…
166 // remove an object from the registry. deletes lo and the underlying c++
167 // object if necessary
5cabc0d5 »
2011-03-27 rename the object classes a bit
168 static void Deregister(LuaObjectBase *lo);
08e2c81b »
2011-03-18 lua object wrapper baseclass
169
4c3f4ec6 »
2011-04-26 add existence test for all exposed objects
170 // lua method to determine if the underlying object is still present in
171 // the registry (ie still exists)
9665caa1 »
2011-05-06 follow c method naming convention
172 static int l_exists(lua_State *l);
4c3f4ec6 »
2011-04-26 add existence test for all exposed objects
173
0a73a7f5 »
2011-05-06 lua-side object isa method
174 // lua method to determine if the object inherits from a type. wrapper
175 // around ::Isa()
176 static int l_isa(lua_State *l);
177
77df8e3a »
2011-03-23 look at me, documenting stuff
178 // the lua object "destructor" that gets called by the garbage collector.
179 // its only part of the class so that it can call Deregister()
9665caa1 »
2011-05-06 follow c method naming convention
180 static int l_gc(lua_State *l);
c6beeaf7 »
2011-03-21 rework as true wrappers rather than just type magic things. still war…
181
97292fa8 »
2012-06-20 slightly more informative default tostring for userdata objects
182 // default tostring. shows a little more info about the object, like its
183 // type
184 static int l_tostring(lua_State *l);
185
1789f632 »
2011-03-31 let LuaSerializer get at the objects inside
186 // pull an LuaObjectBase wrapper from the registry given an id. returns NULL
187 // if the object is not in the registry
188 static LuaObjectBase *Lookup(lid id);
189
190 // determine if the object has a class in its ancestry
7654ae49 »
2011-05-06 fix LuaObject::Isa, it was all kinds of broken
191 bool Isa(const char *base) const;
1789f632 »
2011-03-31 let LuaSerializer get at the objects inside
192
77df8e3a »
2011-03-23 look at me, documenting stuff
193 // object id, pointer to the c++ object and lua type string
aea91939 »
2011-03-21 if you want to go to lua you gotta tell me when you're about to die
194 lid m_id;
195 DeleteEmitter *m_object;
196 const char *m_type;
4fb07bca »
2011-03-22 disconnect from delete signals when no longer interested
197
77df8e3a »
2011-03-23 look at me, documenting stuff
198 // flag to indicate that lua owns the object and should delete it when its
199 // deregistered
200 bool m_wantDelete;
9b514b0b »
2011-03-22 method to allow lua to take ownership of an object (ie destruction ti…
201
77df8e3a »
2011-03-23 look at me, documenting stuff
202 // the wrapper object's connection to the deletion signal. this gets
203 // connected on registration and disconnected on deregistration
4fb07bca »
2011-03-22 disconnect from delete signals when no longer interested
204 sigc::connection m_deleteConnection;
c6beeaf7 »
2011-03-21 rework as true wrappers rather than just type magic things. still war…
205 };
dede6c56 »
2011-03-21 abstract out the object unpacking
206
77df8e3a »
2011-03-23 look at me, documenting stuff
207
12ffbe2a »
2011-04-12 doc update and some reshuffling
208 // basic acquirer template. used by the wrapper to implement
209 // LuaObjectBase::Acquire and LuaObjectBase::Release. this is the general
210 // case, which does nothing at all
054d9b45 »
2011-04-12 move the acquire/release stuff into a seperate class so that starsyst…
211 template <typename T>
212 class LuaAcquirer {
213 public:
1a988446 »
2011-10-28 fix more method name reuse
214 virtual void OnAcquire(T *) {}
215 virtual void OnRelease(T *) {}
054d9b45 »
2011-04-12 move the acquire/release stuff into a seperate class so that starsyst…
216 };
217
ed78fa90 »
2012-06-14 generalise the refcounted acquirer
218 // acquirer baseclass for RefCounted types. subclass this when you need Lua to
219 // take a reference to an object
220 class LuaAcquirerRefCounted {
221 public:
222 virtual void OnAcquire(RefCounted *o) {
223 o->IncRefCount();
224 }
225 virtual void OnRelease(RefCounted *o) {
226 o->DecRefCount();
227 }
228 };
054d9b45 »
2011-04-12 move the acquire/release stuff into a seperate class so that starsyst…
229
77df8e3a »
2011-03-23 look at me, documenting stuff
230 // template for a wrapper class
b13fc05b »
2011-03-21 template the subobject class
231 template <typename T>
054d9b45 »
2011-04-12 move the acquire/release stuff into a seperate class so that starsyst…
232 class LuaObject : public LuaObjectBase, LuaAcquirer<T> {
b13fc05b »
2011-03-21 template the subobject class
233 public:
77df8e3a »
2011-03-23 look at me, documenting stuff
234
235 // registers the class with the lua vm
2f38ace9 »
2011-04-12 remove the methods tables and inherit name from the class def; they'r…
236 static void RegisterClass();
b13fc05b »
2011-03-21 template the subobject class
237
77df8e3a »
2011-03-23 look at me, documenting stuff
238 // wrap the object and push it onto the lua stack
fec5b1ef »
2011-03-23 push to lua stack on creation, don't return, remove public interface.…
239 static inline void PushToLua(T *o) {
ae6776e1 »
2011-04-10 have the wrapper class create the object wrapper so that it has the r…
240 if (! LuaObjectBase::PushRegistered(o))
77686229 »
2011-04-11 a hack job to get a working specialization for LuaObject<StarSystem> …
241 LuaObjectBase::Push(new LuaObject(o), false);
9b514b0b »
2011-03-22 method to allow lua to take ownership of an object (ie destruction ti…
242 }
243
77df8e3a »
2011-03-23 look at me, documenting stuff
244 // wrap the object and push it onto the lua stack, taking ownership of it
fec5b1ef »
2011-03-23 push to lua stack on creation, don't return, remove public interface.…
245 static inline void PushToLuaGC(T *o) {
ae6776e1 »
2011-04-10 have the wrapper class create the object wrapper so that it has the r…
246 if (! LuaObjectBase::PushRegistered(o))
77686229 »
2011-04-11 a hack job to get a working specialization for LuaObject<StarSystem> …
247 LuaObjectBase::Push(new LuaObject(o), true);
a2ef76fd »
2011-03-22 rework to use heap-allocated luaobjects only
248 }
249
77df8e3a »
2011-03-23 look at me, documenting stuff
250 // pull an object off the the stack, unwrap it and return it
9d6dcc6f »
2011-03-28 change pullfromlua to getfromlua so that type exceptions show the cor…
251 static inline T *GetFromLua(int index) {
252 return dynamic_cast<T *>(LuaObjectBase::GetFromLua(index, s_type));
b13fc05b »
2011-03-21 template the subobject class
253 }
254
9f297b0b »
2011-04-12 checkfromlua to complement getfromlua
255 static inline T *CheckFromLua(int index) {
256 return dynamic_cast<T *>(LuaObjectBase::CheckFromLua(index, s_type));
257 }
258
0d187d13 »
2012-06-14 templated dynamic-casting promotion test for lua objects since its th…
259 // convenience promotion test
260 static inline bool DynamicCastPromotionTest(DeleteEmitter *o) {
261 return dynamic_cast<T *>(o);
262 }
263
77686229 »
2011-04-11 a hack job to get a working specialization for LuaObject<StarSystem> …
264 protected:
12ffbe2a »
2011-04-12 doc update and some reshuffling
265 // hook up the appropriate acquirer for the wrapped object.
1a988446 »
2011-10-28 fix more method name reuse
266 virtual void Acquire(DeleteEmitter *o) { this->LuaAcquirer<T>::OnAcquire(dynamic_cast<T*>(o)); }
267 virtual void Release(DeleteEmitter *o) { this->LuaAcquirer<T>::OnRelease(dynamic_cast<T*>(o)); }
77686229 »
2011-04-11 a hack job to get a working specialization for LuaObject<StarSystem> …
268
269 private:
054d9b45 »
2011-04-12 move the acquire/release stuff into a seperate class so that starsyst…
270 LuaObject(T *o) : LuaObjectBase(o, s_type) {}
77686229 »
2011-04-11 a hack job to get a working specialization for LuaObject<StarSystem> …
271
2f38ace9 »
2011-04-12 remove the methods tables and inherit name from the class def; they'r…
272 // lua type string. this is defined per wrapper class in the appropriate
273 // .cpp file
77686229 »
2011-04-11 a hack job to get a working specialization for LuaObject<StarSystem> …
274 static const char *s_type;
275 };
276
277
7cef0470 »
2011-03-23 template the uncopyable stuff
278 // this one is more complicated. if a class needs to be copyable it can't
5cabc0d5 »
2011-03-27 rename the object classes a bit
279 // inherit from DeleteEmitter as required to be wrapped by LuaObject. so we
b10fb055 »
2011-03-24 fix the comments to make it clearer that LuaUncopyable wrapped classe…
280 // create a new class and inherit from both. it takes a full copy of the
281 // original when instantiated, so is decoupled from the original
7cef0470 »
2011-03-23 template the uncopyable stuff
282 template <typename T>
b10fb055 »
2011-03-24 fix the comments to make it clearer that LuaUncopyable wrapped classe…
283 class LuaUncopyable : public T, public DeleteEmitter {
7cef0470 »
2011-03-23 template the uncopyable stuff
284 public:
b10fb055 »
2011-03-24 fix the comments to make it clearer that LuaUncopyable wrapped classe…
285 LuaUncopyable(const T &p) : T(p), DeleteEmitter() {}
286 private:
287 LuaUncopyable() {}
288 LuaUncopyable(const LuaUncopyable &) {}
7cef0470 »
2011-03-23 template the uncopyable stuff
289 };
290
b10fb055 »
2011-03-24 fix the comments to make it clearer that LuaUncopyable wrapped classe…
291 // if we wanted we could just use LuaUncopyable<T> as-is, but that would mean
7cef0470 »
2011-03-23 template the uncopyable stuff
292 // having to create a uncopyable of every object before passing it to
9d6dcc6f »
2011-03-28 change pullfromlua to getfromlua so that type exceptions show the cor…
293 // PushToLua() and always casting the return from GetFromLua(). instead we
5cabc0d5 »
2011-03-27 rename the object classes a bit
294 // subclass the object and implement some wrapper methods for the "real"
7cef0470 »
2011-03-23 template the uncopyable stuff
295 // types.
296 template <typename T, typename UT>
5cabc0d5 »
2011-03-27 rename the object classes a bit
297 class LuaObjectUncopyable : LuaObject<UT> {
7cef0470 »
2011-03-23 template the uncopyable stuff
298 public:
5cabc0d5 »
2011-03-27 rename the object classes a bit
299 static inline void RegisterClass() { LuaObject<UT>::RegisterClass(); }
7cef0470 »
2011-03-23 template the uncopyable stuff
300
301 // create an uncopyable version and pass it in. we use PushToLuaGC because
302 // this is our object and we have to clean it up
303 static inline void PushToLua(T *p) {
304 UT *up = new UT(*p);
5cabc0d5 »
2011-03-27 rename the object classes a bit
305 LuaObject<UT>::PushToLuaGC(up);
7cef0470 »
2011-03-23 template the uncopyable stuff
306 }
307
308 // same idea, but caller asked us to clean it up when we're done so we
309 // have to do that straight away
310 static inline void PushToLuaGC(T *p) {
311 UT *up = new UT(*p);
312 delete p;
5cabc0d5 »
2011-03-27 rename the object classes a bit
313 LuaObject<UT>::PushToLuaGC(up);
7cef0470 »
2011-03-23 template the uncopyable stuff
314 }
315
316 // pull from lua, casting back to the original type
9d6dcc6f »
2011-03-28 change pullfromlua to getfromlua so that type exceptions show the cor…
317 static inline T *GetFromLua(int index) {
318 return dynamic_cast<T*>(LuaObject<UT>::GetFromLua(index));
7cef0470 »
2011-03-23 template the uncopyable stuff
319 }
9f297b0b »
2011-04-12 checkfromlua to complement getfromlua
320
321 static inline T *CheckFromLua(int index) {
322 return dynamic_cast<T*>(LuaObject<UT>::CheckFromLua(index));
323 }
4006e469 »
2012-04-03 more fixes and cleanups
324
9a010206 »
2012-03-31 A pass of warnings removal for MSVC. Most of them are fixed.
325 private:
4006e469 »
2012-04-03 more fixes and cleanups
326 LuaObjectUncopyable() {}
7cef0470 »
2011-03-23 template the uncopyable stuff
327 };
328
08e2c81b »
2011-03-18 lua object wrapper baseclass
329 #endif
Something went wrong with that request. Please try again.