00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef _DILUCULUM_LUA_WRAPPERS_HPP_
00028 #define _DILUCULUM_LUA_WRAPPERS_HPP_
00029
00030 #include <algorithm>
00031 #include <string>
00032 #include <boost/bind.hpp>
00033 #include <Diluculum/LuaExceptions.hpp>
00034 #include <Diluculum/LuaState.hpp>
00035 #include <Diluculum/LuaUtils.hpp>
00036
00037
00038 namespace Diluculum
00039 {
00040 namespace Impl
00041 {
00050 void ReportErrorFromCFunction (lua_State* ls, const::std::string& what);
00051
00052
00053
00057 struct CppObject
00058 {
00059 public:
00061 void* ptr;
00062
00068 bool deleteMe;
00069 };
00070
00071
00072
00079 class ClassTableFiller
00080 {
00081 public:
00090 ClassTableFiller (Diluculum::LuaValueMap& classTable,
00091 const std::string& name,
00092 lua_CFunction func)
00093 {
00094 classTable[name] = func;
00095 }
00096 };
00097 }
00098 }
00099
00100
00101
00106 #define DILUCULUM_WRAPPER_FUNCTION(FUNC) \
00107 Diluculum__ ## FUNC ## __Wrapper_Function
00108
00109
00110
00130 #define DILUCULUM_WRAP_FUNCTION(FUNC) \
00131 int DILUCULUM_WRAPPER_FUNCTION(FUNC) (lua_State* ls) \
00132 { \
00133 using std::for_each; \
00134 using boost::bind; \
00135 using Diluculum::PushLuaValue; \
00136 using Diluculum::Impl::ReportErrorFromCFunction; \
00137 \
00138 try \
00139 { \
00140 \
00141 const int numParams = lua_gettop (ls); \
00142 Diluculum::LuaValueList params; \
00143 for (int i = 1; i <= numParams; ++i) \
00144 params.push_back (Diluculum::ToLuaValue (ls, i)); \
00145 lua_pop (ls, numParams); \
00146 \
00147 \
00148 Diluculum::LuaValueList ret = FUNC (params); \
00149 \
00150 \
00151 for_each (ret.begin(), ret.end(), bind (PushLuaValue, ls, _1)); \
00152 \
00153 return ret.size(); \
00154 } \
00155 catch (Diluculum::LuaError& e) \
00156 { \
00157 ReportErrorFromCFunction (ls, e.what()); \
00158 return 0; \
00159 } \
00160 catch(...) \
00161 { \
00162 ReportErrorFromCFunction (ls, "Unknown exception caught by wrapper."); \
00163 return 0; \
00164 } \
00165 }
00166
00167
00168
00172 #define DILUCULUM_CLASS_TABLE(CLASS) \
00173 Diluculum__Class_Table__ ## CLASS
00174
00175
00176
00182 #define DILUCULUM_BEGIN_CLASS(CLASS) \
00183 namespace \
00184 { \
00185 \
00186 Diluculum::LuaValueMap DILUCULUM_CLASS_TABLE(CLASS); \
00187 } \
00188 \
00189 \
00190 int Diluculum__ ## CLASS ## __Constructor_Wrapper_Function (lua_State* ls) \
00191 { \
00192 using Diluculum::PushLuaValue; \
00193 using Diluculum::Impl::CppObject; \
00194 using Diluculum::Impl::ReportErrorFromCFunction; \
00195 \
00196 try \
00197 { \
00198 \
00199 const int numParams = lua_gettop (ls); \
00200 Diluculum::LuaValueList params; \
00201 for (int i = 1; i <= numParams; ++i) \
00202 params.push_back (Diluculum::ToLuaValue (ls, i)); \
00203 lua_pop (ls, numParams); \
00204 \
00205 \
00206 void* ud = lua_newuserdata (ls, sizeof(CppObject)); \
00207 CppObject* cppObj = reinterpret_cast<CppObject*>(ud); \
00208 cppObj->ptr = new CLASS (params); \
00209 cppObj->deleteMe = true; \
00210 \
00211 lua_getglobal (ls, "__Diluculum__Class_Metatables"); \
00212 lua_getfield (ls, -1, #CLASS); \
00213 lua_setmetatable (ls, -3); \
00214 lua_pop (ls, 1); \
00215 \
00216 return 1; \
00217 } \
00218 catch (Diluculum::LuaError& e) \
00219 { \
00220 ReportErrorFromCFunction (ls, e.what()); \
00221 return 0; \
00222 } \
00223 catch(...) \
00224 { \
00225 ReportErrorFromCFunction (ls, "Unknown exception caught by wrapper."); \
00226 return 0; \
00227 } \
00228 } \
00229 \
00230 \
00231 int Diluculum__ ## CLASS ## __Destructor_Wrapper_Function (lua_State* ls) \
00232 { \
00233 using Diluculum::Impl::CppObject; \
00234 \
00235 CppObject* cppObj = \
00236 reinterpret_cast<CppObject*>(lua_touserdata (ls, -1)); \
00237 \
00238 if (cppObj->deleteMe) \
00239 { \
00240 cppObj->deleteMe = false; \
00241 CLASS* pObj = reinterpret_cast<CLASS*>(cppObj->ptr); \
00242 delete pObj; \
00243 } \
00244 \
00245 return 0; \
00246 }
00247
00248
00249
00254 #define DILUCULUM_METHOD_WRAPPER(CLASS, METHOD) \
00255 Diluculum__ ## CLASS ## __ ## METHOD ## __Method_Wrapper_Function
00256
00257
00258
00264 #define DILUCULUM_CLASS_METHOD(CLASS, METHOD) \
00265 int DILUCULUM_METHOD_WRAPPER(CLASS, METHOD) (lua_State* ls) \
00266 { \
00267 using std::for_each; \
00268 using boost::bind; \
00269 using Diluculum::PushLuaValue; \
00270 using Diluculum::Impl::CppObject; \
00271 using Diluculum::Impl::ReportErrorFromCFunction; \
00272 \
00273 try \
00274 { \
00275 \
00276 const int numParams = lua_gettop (ls); \
00277 Diluculum::LuaValue ud = Diluculum::ToLuaValue (ls, 1); \
00278 Diluculum::LuaValueList params; \
00279 for (int i = 2; i <= numParams; ++i) \
00280 params.push_back (Diluculum::ToLuaValue (ls, i)); \
00281 lua_pop (ls, numParams); \
00282 \
00283 \
00284 CppObject* cppObj = \
00285 reinterpret_cast<CppObject*>(ud.asUserData().getData()); \
00286 CLASS* pObj = reinterpret_cast<CLASS*>(cppObj->ptr); \
00287 \
00288 Diluculum::LuaValueList ret = pObj->METHOD (params); \
00289 \
00290 \
00291 for_each (ret.begin(), ret.end(), bind (PushLuaValue, ls, _1)); \
00292 \
00293 return ret.size(); \
00294 } \
00295 catch (Diluculum::LuaError& e) \
00296 { \
00297 ReportErrorFromCFunction (ls, e.what()); \
00298 return 0; \
00299 } \
00300 catch(...) \
00301 { \
00302 ReportErrorFromCFunction (ls, "Unknown exception caught by wrapper."); \
00303 return 0; \
00304 } \
00305 } \
00306 \
00307 namespace \
00308 { \
00309 Diluculum::Impl::ClassTableFiller \
00310 Diluculum__ ## CLASS ## _ ## METHOD ## __ ## Filler( \
00311 DILUCULUM_CLASS_TABLE(CLASS), \
00312 #METHOD, \
00313 DILUCULUM_METHOD_WRAPPER(CLASS, METHOD)); \
00314 }
00315
00316
00317
00322 #define DILUCULUM_END_CLASS(CLASS) \
00323 \
00324 \
00325 void Diluculum_Register_Class__ ## CLASS (Diluculum::LuaVariable className) \
00326 { \
00327 Diluculum::LuaState ls (className.getState()); \
00328 \
00329 if (ls["__Diluculum__Class_Metatables"].value().type() == LUA_TNIL) \
00330 ls["__Diluculum__Class_Metatables"] = Diluculum::EmptyLuaValueMap; \
00331 \
00332 DILUCULUM_CLASS_TABLE(CLASS)["classname"] = #CLASS; \
00333 \
00334 DILUCULUM_CLASS_TABLE(CLASS)["new"] = \
00335 Diluculum__ ## CLASS ## __Constructor_Wrapper_Function; \
00336 \
00337 DILUCULUM_CLASS_TABLE(CLASS)["delete"] = \
00338 Diluculum__ ## CLASS ## __Destructor_Wrapper_Function; \
00339 \
00340 DILUCULUM_CLASS_TABLE(CLASS)["__gc"] = \
00341 Diluculum__ ## CLASS ## __Destructor_Wrapper_Function; \
00342 \
00343 DILUCULUM_CLASS_TABLE(CLASS)["__index"] = DILUCULUM_CLASS_TABLE(CLASS); \
00344 \
00345 className = DILUCULUM_CLASS_TABLE(CLASS); \
00346 \
00347 ls["__Diluculum__Class_Metatables"][#CLASS] = \
00348 DILUCULUM_CLASS_TABLE(CLASS); \
00349 }
00350
00351
00352
00360 #define DILUCULUM_REGISTER_CLASS(LUA_VARIABLE, CLASS) \
00361 Diluculum_Register_Class__ ## CLASS (LUA_VARIABLE);
00362
00363
00364
00378 #define DILUCULUM_REGISTER_OBJECT(LUA_VARIABLE, CLASS, OBJECT) \
00379 { \
00380 \
00381 LUA_VARIABLE.pushLastTable(); \
00382 \
00383 \
00384 Diluculum::PushLuaValue (LUA_VARIABLE.getState(), \
00385 LUA_VARIABLE.getKeys().back()); \
00386 \
00387 \
00388 void* ud = lua_newuserdata (LUA_VARIABLE.getState(), \
00389 sizeof(Diluculum::Impl::CppObject)); \
00390 \
00391 Diluculum::Impl::CppObject* cppObj = \
00392 reinterpret_cast<Diluculum::Impl::CppObject*>(ud); \
00393 \
00394 cppObj->ptr = &OBJECT; \
00395 cppObj->deleteMe = false; \
00396 \
00397 lua_getglobal (LUA_VARIABLE.getState(), "__Diluculum__Class_Metatables"); \
00398 lua_getfield (LUA_VARIABLE.getState(), -1, #CLASS); \
00399 lua_setmetatable (LUA_VARIABLE.getState(), -3); \
00400 \
00401 lua_pop (LUA_VARIABLE.getState(), 1); \
00402 \
00403 \
00404 lua_settable (LUA_VARIABLE.getState(), -3); \
00405 }
00406
00407
00408
00424 #define DILUCULUM_BEGIN_MODULE(MODNAME) \
00425 extern "C" int luaopen_ ## MODNAME (lua_State *luaState) \
00426 { \
00427 using Diluculum::LuaState; \
00428 using Diluculum::LuaVariable; \
00429 using Diluculum::EmptyLuaValueMap; \
00430 LuaState ls (luaState); \
00431 \
00432 ls[#MODNAME] = EmptyLuaValueMap; \
00433 LuaVariable theModule = ls[#MODNAME];
00434
00435
00436
00443 #define DILUCULUM_MODULE_ADD_CLASS(CLASS, LUACLASS) \
00444 DILUCULUM_REGISTER_CLASS(theModule[LUACLASS], CLASS);
00445
00446
00447
00454 #define DILUCULUM_MODULE_ADD_FUNCTION(CFUNC, LUAFUNC) \
00455 theModule[LUAFUNC] = CFUNC;
00456
00457
00458
00462 #define DILUCULUM_END_MODULE() \
00463 return 1; \
00464 }
00465
00466 #endif // _DILUCULUM_LUA_WRAPPERS_HPP_