1 #ifndef LUAGLUE_METHOD_H_GUARD 2 #define LUAGLUE_METHOD_H_GUARD 3 4 #include <lua.hpp> 5 #include <string> 6 #include <tuple> 7 #include <utility> 8 9 #include "LuaGlue/LuaGlueMethodBase.h" 10 #include "LuaGlue/LuaGlueObject.h" 11 #include "LuaGlue/LuaGlueApplyTuple.h" 12 #include "LuaGlue/LuaGlueDebug.h" 13 14 #include "LuaGlue/LuaGlueBase.h" 15 16 template<typename _Class> 17 class LuaGlueClass; 18 19 template<typename _Ret, typename _Class, typename... _Args> 20 class LuaGlueMethod : public LuaGlueMethodBase 21 { 22 private: 23 template < typename... T > 24 struct tuple 25 { 26 typedef std::tuple<typename std::remove_const<typename std::remove_reference<T>::type>::type...> type; 27 }; 28 29 public: 30 typedef _Class ClassType; 31 typedef _Ret ReturnType; 32 typedef _Ret (_Class::*MethodType)( _Args... ); 33 LuaGlueMethod(LuaGlueClass<_Class> * luaClass,const std::string & name,MethodType && fn)34 LuaGlueMethod(LuaGlueClass<_Class> *luaClass, const std::string &name, MethodType &&fn) : glueClass(luaClass), name_(name), fn(std::forward<decltype(fn)>(fn)) 35 { /*printf("new class %s method %s\n", typeid(_Class).name(), typeid(MethodType).name());*/ } 36 ~LuaGlueMethod()37 ~LuaGlueMethod() {} 38 name()39 std::string name() { return name_; } 40 glue(LuaGlueBase * luaGlue)41 bool glue(LuaGlueBase *luaGlue) 42 { 43 lua_pushlightuserdata(luaGlue->state(), this); 44 lua_pushcclosure(luaGlue->state(), &lua_call_func, 1); 45 lua_setfield(luaGlue->state(), -2, name_.c_str()); 46 return true; 47 } 48 49 private: 50 LuaGlueClass<_Class> *glueClass; 51 std::string name_; 52 MethodType fn; 53 std::tuple<_Args...> args; 54 static const unsigned int Arg_Count_ = sizeof...(_Args); 55 56 public: invoke(lua_State * state)57 int invoke(lua_State *state) 58 { 59 ReturnType ret; 60 61 auto base = GetLuaUdata(state, 1, glueClass->name().c_str()); 62 if(base->isSharedPtr()) 63 { 64 auto obj = *CastLuaGlueObjectShared(ClassType, base); 65 ret = applyTuple(glueClass->luaGlue(), state, obj, fn, args); 66 } 67 else 68 { 69 auto obj = *CastLuaGlueObject(ClassType, base); 70 ret = applyTuple(glueClass->luaGlue(), state, obj, fn, args); 71 } 72 73 if(Arg_Count_) lua_pop(state, (int)Arg_Count_); 74 75 stack<ReturnType>::put(glueClass->luaGlue(), state, ret); 76 return 1; 77 } 78 79 private: lua_call_func(lua_State * state)80 static int lua_call_func(lua_State *state) 81 { 82 auto mimp = (LuaGlueMethod<_Ret, _Class, _Args...> *)lua_touserdata(state, lua_upvalueindex(1)); 83 return mimp->invoke(state); 84 } 85 }; 86 87 template<typename _Class, typename... _Args> 88 class LuaGlueMethod<void, _Class, _Args...> : public LuaGlueMethodBase 89 { 90 private: 91 template <typename... T> 92 struct tuple 93 { 94 typedef std::tuple<typename std::remove_const<typename std::remove_reference<T>::type>::type...> type; 95 }; 96 97 public: 98 typedef _Class ClassType; 99 typedef void (_Class::*MethodType)(_Args...); 100 LuaGlueMethod(LuaGlueClass<_Class> * luaClass,const std::string & name,MethodType && fn)101 LuaGlueMethod(LuaGlueClass<_Class> *luaClass, const std::string &name, MethodType &&fn) : glueClass(luaClass), name_(name), fn(std::forward<decltype(fn)>(fn)) 102 { /*printf("new class %s method %s\n", typeid(_Class).name(), typeid(MethodType).name());*/ } 103 ~LuaGlueMethod()104 ~LuaGlueMethod() {} 105 name()106 std::string name() { return name_; } 107 glue(LuaGlueBase * luaGlue)108 bool glue(LuaGlueBase *luaGlue) 109 { 110 lua_pushlightuserdata(luaGlue->state(), this); 111 lua_pushcclosure(luaGlue->state(), &lua_call_func, 1); 112 lua_setfield(luaGlue->state(), -2, name_.c_str()); 113 return true; 114 } 115 116 private: 117 LuaGlueClass<_Class> *glueClass; 118 std::string name_; 119 MethodType fn; 120 std::tuple<_Args...> args; 121 static const unsigned int Arg_Count_ = sizeof...(_Args); 122 123 public: invoke(lua_State * state)124 int invoke(lua_State *state) 125 { 126 //printf("invokev: %s::%s\n", typeid(*glueClass).name(), name_.c_str()); 127 128 auto base = GetLuaUdata(state, 1, glueClass->name().c_str()); 129 if(base->isSharedPtr()) 130 { 131 auto obj = *CastLuaGlueObjectShared(ClassType, base); 132 applyTuple(glueClass->luaGlue(), state, obj, fn, args); 133 } 134 else 135 { 136 auto obj = *CastLuaGlueObject(ClassType, base); 137 applyTuple(glueClass->luaGlue(), state, obj, fn, args); 138 } 139 140 if(Arg_Count_) lua_pop(state, (int)Arg_Count_); 141 return 0; 142 } 143 144 private: lua_call_func(lua_State * state)145 static int lua_call_func(lua_State *state) 146 { 147 auto mimp = (LuaGlueMethod<void, _Class, _Args...> *)lua_touserdata(state, lua_upvalueindex(1)); 148 return mimp->invoke(state); 149 } 150 }; 151 152 template<typename _Ret, typename _Class, typename... _Args> 153 class LuaGlueConstMethod : public LuaGlueMethodBase 154 { 155 private: 156 template <typename... T> 157 struct tuple 158 { 159 typedef std::tuple<typename std::remove_const<typename std::remove_reference<T>::type>::type...> type; 160 }; 161 162 public: 163 typedef _Class ClassType; 164 typedef _Ret ReturnType; 165 typedef _Ret (_Class::*MethodType)( _Args... ) const; 166 LuaGlueConstMethod(LuaGlueClass<_Class> * luaClass,const std::string & name,MethodType && fn)167 LuaGlueConstMethod(LuaGlueClass<_Class> *luaClass, const std::string &name, MethodType &&fn) : glueClass(luaClass), name_(name), fn(std::forward<decltype(fn)>(fn)) 168 { /*printf("new class %s method %s\n", typeid(_Class).name(), typeid(MethodType).name());*/ } 169 ~LuaGlueConstMethod()170 ~LuaGlueConstMethod() {} 171 name()172 std::string name() { return name_; } 173 glue(LuaGlueBase * luaGlue)174 bool glue(LuaGlueBase *luaGlue) 175 { 176 lua_pushlightuserdata(luaGlue->state(), this); 177 lua_pushcclosure(luaGlue->state(), &lua_call_func, 1); 178 lua_setfield(luaGlue->state(), -2, name_.c_str()); 179 return true; 180 } 181 182 private: 183 LuaGlueClass<_Class> *glueClass; 184 std::string name_; 185 MethodType fn; 186 tuple<_Args...> args; 187 static const unsigned int Arg_Count_ = sizeof...(_Args); 188 189 public: invoke(lua_State * state)190 int invoke(lua_State *state) 191 { 192 //printf("invoker: %s::%s\n", typeid(*glueClass).name(), name_.c_str()); 193 194 ReturnType ret; 195 auto base = GetLuaUdata(state, 1, glueClass->name().c_str()); 196 if(base->isSharedPtr()) 197 { 198 LuaGlueObject<std::shared_ptr<ClassType>> obj = *CastLuaGlueObjectShared(ClassType, base); 199 ret = applyTuple(glueClass->luaGlue(), state, obj, fn, args); 200 } 201 else 202 { 203 auto obj = *CastLuaGlueObject(ClassType, base); 204 ret = applyTuple(glueClass->luaGlue(), state, obj, fn, args); 205 } 206 207 if(Arg_Count_) lua_pop(state, (int)Arg_Count_); 208 209 stack<ReturnType>::put(glueClass->luaGlue(), state, ret); 210 return 1; 211 } 212 213 private: lua_call_func(lua_State * state)214 static int lua_call_func(lua_State *state) 215 { 216 auto mimp = (LuaGlueConstMethod<_Ret, _Class, _Args...> *)lua_touserdata(state, lua_upvalueindex(1)); 217 return mimp->invoke(state); 218 } 219 }; 220 221 template<typename _Class, typename... _Args> 222 class LuaGlueConstMethod<void, _Class, _Args...> : public LuaGlueMethodBase 223 { 224 private: 225 template <typename... T> 226 struct tuple 227 { 228 typedef std::tuple<typename std::remove_const<typename std::remove_reference<T>::type>::type...> type; 229 }; 230 231 public: 232 typedef _Class ClassType; 233 typedef void (_Class::*MethodType)(_Args...) const; 234 LuaGlueConstMethod(LuaGlueClass<_Class> * luaClass,const std::string & name,MethodType && fn)235 LuaGlueConstMethod(LuaGlueClass<_Class> *luaClass, const std::string &name, MethodType &&fn) : glueClass(luaClass), name_(name), fn(std::forward<decltype(fn)>(fn)) 236 { /*printf("new class %s method %s\n", typeid(_Class).name(), typeid(MethodType).name());*/ } 237 ~LuaGlueConstMethod()238 ~LuaGlueConstMethod() {} 239 name()240 std::string name() { return name_; } 241 glue(LuaGlueBase * luaGlue)242 bool glue(LuaGlueBase *luaGlue) 243 { 244 lua_pushlightuserdata(luaGlue->state(), this); 245 lua_pushcclosure(luaGlue->state(), &lua_call_func, 1); 246 lua_setfield(luaGlue->state(), -2, name_.c_str()); 247 return true; 248 } 249 250 private: 251 LuaGlueClass<_Class> *glueClass; 252 std::string name_; 253 MethodType fn; 254 std::tuple<_Args...> args; 255 static const unsigned int Arg_Count_ = sizeof...(_Args); 256 257 public: invoke(lua_State * state)258 int invoke(lua_State *state) 259 { 260 //printf("invokev: %s::%s\n", typeid(*glueClass).name(), name_.c_str()); 261 262 auto base = GetLuaUdata(state, 1, glueClass->name().c_str()); 263 if(base->isSharedPtr()) 264 { 265 auto obj = *CastLuaGlueObjectShared(ClassType, base); 266 applyTuple(glueClass->luaGlue(), state, obj, fn, args); 267 } 268 else 269 { 270 auto obj = *CastLuaGlueObject(ClassType, base); 271 applyTuple(glueClass->luaGlue(), state, obj, fn, args); 272 } 273 274 if(Arg_Count_) lua_pop(state, (int)Arg_Count_); 275 return 0; 276 } 277 278 private: lua_call_func(lua_State * state)279 static int lua_call_func(lua_State *state) 280 { 281 auto mimp = (LuaGlueConstMethod<void, _Class, _Args...> *)lua_touserdata(state, lua_upvalueindex(1)); 282 return mimp->invoke(state); 283 } 284 }; 285 286 // shared_ptr specializations 287 288 template<typename _Ret, typename _Class, typename... _Args> 289 class LuaGlueMethod<_Ret, std::shared_ptr<_Class>, _Args...> : public LuaGlueMethodBase 290 { 291 private: 292 template <typename... T> 293 struct tuple 294 { 295 typedef std::tuple<typename std::remove_const<typename std::remove_reference<T>::type>::type...> type; 296 }; 297 298 public: 299 typedef _Class ClassType; 300 typedef std::shared_ptr<_Class> SharedType; 301 typedef _Ret ReturnType; 302 typedef _Ret (_Class::*MethodType)( _Args... ); 303 LuaGlueMethod(LuaGlueClass<ClassType> * luaClass,const std::string & name,MethodType && fn)304 LuaGlueMethod(LuaGlueClass<ClassType> *luaClass, const std::string &name, MethodType &&fn) : glueClass(luaClass), name_(name), fn(std::forward<decltype(fn)>(fn)) 305 {} 306 ~LuaGlueMethod()307 ~LuaGlueMethod() {} 308 name()309 std::string name() { return name_; } 310 glue(LuaGlueBase * luaGlue)311 bool glue(LuaGlueBase *luaGlue) 312 { 313 lua_pushlightuserdata(luaGlue->state(), this); 314 lua_pushcclosure(luaGlue->state(), &lua_call_func, 1); 315 lua_setfield(luaGlue->state(), -2, name_.c_str()); 316 return true; 317 } 318 319 private: 320 LuaGlueClass<_Class> *glueClass; 321 std::string name_; 322 MethodType fn; 323 tuple<_Args...> args; 324 static const unsigned int Arg_Count_ = sizeof...(_Args); 325 326 public: invoke(lua_State * state)327 int invoke(lua_State *state) 328 { 329 //printf("invoker: %s::%s\n", typeid(*glueClass).name(), name_.c_str()); 330 331 ReturnType ret; 332 auto base = GetLuaUdata(state, 1, glueClass->name().c_str()); 333 if(base->isSharedPtr()) 334 { 335 auto obj = *CastLuaGlueObjectShared(ClassType, base); 336 ret = applyTuple(glueClass->luaGlue(), state, obj, fn, args); 337 } 338 else 339 { 340 auto obj = *CastLuaGlueObject(ClassType, base); 341 ret = applyTuple(glueClass->luaGlue(), state, obj, fn, args); 342 } 343 344 if(Arg_Count_) lua_pop(state, (int)Arg_Count_); 345 346 stack<ReturnType>::put(glueClass->luaGlue(), state, ret); 347 return 1; 348 } 349 350 private: lua_call_func(lua_State * state)351 static int lua_call_func(lua_State *state) 352 { 353 auto mimp = (LuaGlueMethod<_Ret, _Class, _Args...> *)lua_touserdata(state, lua_upvalueindex(1)); 354 return mimp->invoke(state); 355 } 356 }; 357 358 template<typename _Class, typename... _Args> 359 class LuaGlueMethod<void, std::shared_ptr<_Class>, _Args...> : public LuaGlueMethodBase 360 { 361 private: 362 template <typename... T> 363 struct tuple 364 { 365 typedef std::tuple<typename std::remove_const<typename std::remove_reference<T>::type>::type...> type; 366 }; 367 368 public: 369 typedef _Class ClassType; 370 typedef std::shared_ptr<_Class> SharedType; 371 typedef void (_Class::*MethodType)(_Args...); 372 LuaGlueMethod(LuaGlueClass<_Class> * luaClass,const std::string & name,MethodType && fn)373 LuaGlueMethod(LuaGlueClass<_Class> *luaClass, const std::string &name, MethodType &&fn) : glueClass(luaClass), name_(name), fn(std::forward<decltype(fn)>(fn)) 374 {} 375 ~LuaGlueMethod()376 ~LuaGlueMethod() {} 377 name()378 std::string name() { return name_; } 379 glue(LuaGlueBase * luaGlue)380 bool glue(LuaGlueBase *luaGlue) 381 { 382 lua_pushlightuserdata(luaGlue->state(), this); 383 lua_pushcclosure(luaGlue->state(), &lua_call_func, 1); 384 lua_setfield(luaGlue->state(), -2, name_.c_str()); 385 return true; 386 } 387 388 private: 389 LuaGlueClass<_Class> *glueClass; 390 std::string name_; 391 MethodType fn; 392 std::tuple<_Args...> args; 393 static const unsigned int Arg_Count_ = sizeof...(_Args); 394 395 public: invoke(lua_State * state)396 int invoke(lua_State *state) 397 { 398 //printf("invokev: %s::%s\n", typeid(*glueClass).name(), name_.c_str()); 399 400 auto base = GetLuaUdata(state, 1, glueClass->name().c_str()); 401 if(base->isSharedPtr()) 402 { 403 auto obj = *CastLuaGlueObjectShared(ClassType, base); 404 applyTuple(glueClass->luaGlue(), state, obj, fn, args); 405 } 406 else 407 { 408 auto obj = *CastLuaGlueObject(ClassType, base); 409 applyTuple(glueClass->luaGlue(), state, obj, fn, args); 410 } 411 412 if(Arg_Count_) lua_pop(state, (int)Arg_Count_); 413 return 0; 414 } 415 416 private: lua_call_func(lua_State * state)417 static int lua_call_func(lua_State *state) 418 { 419 auto mimp = (LuaGlueMethod<void, _Class, _Args...> *)lua_touserdata(state, lua_upvalueindex(1)); 420 return mimp->invoke(state); 421 } 422 }; 423 424 425 #endif /* LUAGLUE_METHOD_H_GUARD */ 426