Lua_icxx  1.02 (Aug 2011)
LuaFuncRef.h
00001 /*
00002 This file is part of the Lua_icxx library. 
00003 Copyright 2010 (c) by Oliver Schoenborn. 
00004 License terms in LICENSE.txt.
00005 */
00006 
00007 
00008 #pragma once
00009 
00010 #ifndef LUA_ICXX_FUNCREF_INCLUDED
00011 #define LUA_ICXX_FUNCREF_INCLUDED
00012 
00013 
00014 #include "LuaObjRef.h"
00015 #include "LuaAdapters.h"
00016 #include "luaFuncCalls.h"
00017 
00018 
00019 class LuaFuncCallParams;
00020 class LuaTableRef;
00021 
00022 
00029 class LUA_ICXX_CPP_API
00030 LuaFuncRef: public LuaObjRef
00031 {
00032 public: 
00034     explicit LuaFuncRef( const std::string& id = "nil" ): LuaObjRef(id) {}
00035 
00037 
00038     LuaFuncRef( const LuaTempResult& res): LuaObjRef(res) {}
00039     LuaFuncRef( const LuaTempResult::Item& item): LuaObjRef(item) {}
00040     LuaFuncRef( lua_State* lua, int stackPos ): LuaObjRef(lua, stackPos) {}
00042 
00044     bool setEnv(const LuaTableRef&);
00048     LuaTempResult getEnv() const;
00049 
00051 
00052     DECL_FN_CALLS(operator());
00053     DECL_FN_CALLS(call);
00055 
00056 private: 
00057     inline LuaFuncCallParams prepCall() const;
00058 };
00059 
00060 
00070 class LUA_ICXX_CPP_API
00071 LuaBoundMethRef
00072 {
00073 public:
00075     LuaBoundMethRef() {} // nil
00077     LuaBoundMethRef( const LuaObjRef & obj, const LuaFuncRef & fn )
00078         : mMethRef( fn ), mObjRef(obj) {}
00080     LuaBoundMethRef( const LuaTempResult & res )
00081         : mObjRef( res[1] ), mMethRef( res[2] ) {}
00082 
00084 
00085     void resetRef( const LuaObjRef & obj, const LuaFuncRef & fn );
00086     void resetRef( const LuaTempResult& result ) { resetRef(result[1], result[2]); }
00087     LuaBoundMethRef& operator=(const LuaTempResult& result )  { resetRef(result); return *this;}
00089 
00091     bool isNil() const { return mObjRef.isNil() || mMethRef.isNil(); }
00093     std::string typeName() const { return isNil() ? "nil" : "boundmethod"; }
00095     std::string getID() const { return mObjRef.getID() + ":" + mMethRef.getID(); }
00096 
00098 
00099 
00100     DECL_FN_CALLS(operator());
00101     DECL_FN_CALLS(call);
00103 
00104 private:
00105     LuaObjRef   mObjRef;
00106     LuaFuncRef  mMethRef;
00107 };
00108 
00109 
00117 class LUA_ICXX_CPP_API
00118 LuaClassObjRef: public LuaObjRef
00119 {
00120 public:
00122     explicit LuaClassObjRef( const std::string& id = "nil" ): LuaObjRef(id) {}
00124 
00125     LuaClassObjRef( const LuaTempResult& res): LuaObjRef(res) {}
00126     LuaClassObjRef( const LuaTempResult::Item& item): LuaObjRef(item) {}
00127     LuaClassObjRef( lua_State* lua, int stackPos ): LuaObjRef(lua, stackPos) {}
00129 
00131     LuaBoundMethRef getBoundMethod(const std::string&) const;
00132 
00134 
00135 
00136     DECL_FN_CALLS(callMethod);
00138 
00139 private: 
00140     inline LuaFuncCallParams prepCall(const std::string&) const;
00141 };
00142 
00143 
00144 // ----------------------------------------------------------------------
00145 
00162 template <typename TT>
00163 struct NotAllowedAsFunctionArgument 
00164 { 
00166     static inline const TT& ref(const TT& obj) { return obj; } 
00167 };
00168 
00170 template <>
00171 struct NotAllowedAsFunctionArgument<LuaTempResult>;
00172 
00174 template <>
00175 struct NotAllowedAsFunctionArgument<LuaTempResult::Item>;
00176 
00177 
00178 /*  Puts the function call parameters on the Lua stack, makes the call, and 
00179     encapsulates the return values in a LuaTempResult. 
00180     */
00181 class LUA_ICXX_CPP_API
00182 LuaFuncCallParams
00183 {
00184 public:
00185     LuaFuncCallParams(const std::string& funcID, lua_State* lua, int currStackTop, 
00186         int alreadyOnStack = 0)
00187         : mFuncID(funcID.empty() ? "<anonymous>" : funcID), mLua(lua), 
00188         preStackTop(currStackTop), argsOnStack(alreadyOnStack) {}
00189 
00190 public:
00191     template <typename TT>
00192     inline LuaFuncCallParams& operator<<(const TT& obj)
00193     { 
00194         pushValToStack(mLua, NotAllowedAsFunctionArgument<TT>::ref(obj));
00195         argsOnStack ++;
00196         return *this;
00197     }
00198 
00199     LuaTempResult doCall() const 
00200     {
00201         assert(mLua);
00202         const int numRets = LUA_MULTRET;
00203         const int errCode = lua_pcall(mLua, argsOnStack, numRets, 0);
00204         return LuaTempResult(mLua, preStackTop, errCode, "Function call " + mFuncID + "()");
00205     }
00206 
00207     // doesn't work: 
00208     //operator LuaTempResult() const 
00209 
00210 private:
00211     lua_State * mLua;
00212     std::string mFuncID; 
00213     const int preStackTop;
00214     int argsOnStack;
00215 };
00216 
00217 
00218 inline LuaFuncCallParams 
00219 LuaFuncRef::prepCall() 
00220 const 
00221 {
00222     const int curStackTop = (mLua ? lua_gettop(mLua) : 0);
00223     pushObj();
00224     return LuaFuncCallParams(getID(), mLua, curStackTop);
00225 }
00226 
00227 
00228 inline LuaFuncCallParams 
00229 LuaClassObjRef::prepCall(const std::string& methName) 
00230 const 
00231 {
00232     const int curStackTop = (mLua ? lua_gettop(mLua) : 0);
00233     // get method of object:
00234     pushObj();
00235     lua_getfield(mLua, -1, methName.c_str());
00236     // move method before object since object must be first arg to function call: 
00237     lua_insert(mLua, -2);
00238     assert( lua_gettop(mLua) == curStackTop + 2 );
00239     return LuaFuncCallParams(getID(), mLua, curStackTop, 1);
00240 }
00241 
00242 
00243 // ----------- LuaFuncRef::call(...) and operator()(...) for 0 to 9 args of any type ------------------------
00244 
00245 DEF_FN_CALL_0(LuaFuncRef::call,   prepCall().doCall() );
00246 DEF_FN_CALL_1(LuaFuncRef::call, ( prepCall() << arg1 ).doCall() );
00247 DEF_FN_CALL_2(LuaFuncRef::call, ( prepCall() << arg1 << arg2 ).doCall() );
00248 DEF_FN_CALL_3(LuaFuncRef::call, ( prepCall() << arg1 << arg2 << arg3 ).doCall() );
00249 DEF_FN_CALL_4(LuaFuncRef::call, ( prepCall() << arg1 << arg2 << arg3 << arg4 ).doCall() );
00250 DEF_FN_CALL_5(LuaFuncRef::call, ( prepCall() << arg1 << arg2 << arg3 << arg4 << arg5 ).doCall() );
00251 DEF_FN_CALL_6(LuaFuncRef::call, ( prepCall() << arg1 << arg2 << arg3 << arg4 << arg5 << arg6 ).doCall() );
00252 DEF_FN_CALL_7(LuaFuncRef::call, ( prepCall() << arg1 << arg2 << arg3 << arg4 << arg5 << arg6 << arg7 ).doCall() );
00253 DEF_FN_CALL_8(LuaFuncRef::call, ( prepCall() << arg1 << arg2 << arg3 << arg4 << arg5 << arg6 << arg7 << arg8 ).doCall() );
00254 DEF_FN_CALL_9(LuaFuncRef::call, ( prepCall() << arg1 << arg2 << arg3 << arg4 << arg5 << arg6 << arg7 << arg8 << arg9 ).doCall() );
00255 
00256 DEF_FN_CALL_0(LuaFuncRef::operator(), call() );
00257 DEF_FN_CALL_1(LuaFuncRef::operator(), call(arg1) );
00258 DEF_FN_CALL_2(LuaFuncRef::operator(), call(arg1, arg2 ) );
00259 DEF_FN_CALL_3(LuaFuncRef::operator(), call(arg1, arg2, arg3 ) );
00260 DEF_FN_CALL_4(LuaFuncRef::operator(), call(arg1, arg2, arg3, arg4 ) );
00261 DEF_FN_CALL_5(LuaFuncRef::operator(), call(arg1, arg2, arg3, arg4, arg5 ) );
00262 DEF_FN_CALL_6(LuaFuncRef::operator(), call(arg1, arg2, arg3, arg4, arg5, arg6 ) );
00263 DEF_FN_CALL_7(LuaFuncRef::operator(), call(arg1, arg2, arg3, arg4, arg5, arg6, arg7 ) );
00264 DEF_FN_CALL_8(LuaFuncRef::operator(), call(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 ) );
00265 DEF_FN_CALL_9(LuaFuncRef::operator(), call(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 ) );
00266 
00267 
00268 // same for LuaBoundMethRef: 
00269 
00270 DEF_FN_CALL_0(LuaBoundMethRef::call, mMethRef(mObjRef) );
00271 DEF_FN_CALL_1(LuaBoundMethRef::call, mMethRef(mObjRef, arg1) );
00272 DEF_FN_CALL_2(LuaBoundMethRef::call, mMethRef(mObjRef, arg1, arg2) );
00273 DEF_FN_CALL_3(LuaBoundMethRef::call, mMethRef(mObjRef, arg1, arg2, arg3) );
00274 DEF_FN_CALL_4(LuaBoundMethRef::call, mMethRef(mObjRef, arg1, arg2, arg3, arg4) );
00275 DEF_FN_CALL_5(LuaBoundMethRef::call, mMethRef(mObjRef, arg1, arg2, arg3, arg4, arg5) );
00276 DEF_FN_CALL_6(LuaBoundMethRef::call, mMethRef(mObjRef, arg1, arg2, arg3, arg4, arg5, arg6) );
00277 DEF_FN_CALL_7(LuaBoundMethRef::call, mMethRef(mObjRef, arg1, arg2, arg3, arg4, arg5, arg6, arg7) );
00278 DEF_FN_CALL_8(LuaBoundMethRef::call, mMethRef(mObjRef, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) );
00279 DEF_FN_CALL_9(LuaBoundMethRef::call, mMethRef(mObjRef, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) );
00280 
00281 DEF_FN_CALL_0(LuaBoundMethRef::operator(), call() );
00282 DEF_FN_CALL_1(LuaBoundMethRef::operator(), call( arg1) );
00283 DEF_FN_CALL_2(LuaBoundMethRef::operator(), call( arg1, arg2) );
00284 DEF_FN_CALL_3(LuaBoundMethRef::operator(), call( arg1, arg2, arg3) );
00285 DEF_FN_CALL_4(LuaBoundMethRef::operator(), call( arg1, arg2, arg3, arg4) );
00286 DEF_FN_CALL_5(LuaBoundMethRef::operator(), call( arg1, arg2, arg3, arg4, arg5) );
00287 DEF_FN_CALL_6(LuaBoundMethRef::operator(), call( arg1, arg2, arg3, arg4, arg5, arg6) );
00288 DEF_FN_CALL_7(LuaBoundMethRef::operator(), call( arg1, arg2, arg3, arg4, arg5, arg6, arg7) );
00289 DEF_FN_CALL_8(LuaBoundMethRef::operator(), call( arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) );
00290 DEF_FN_CALL_9(LuaBoundMethRef::operator(), call( arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) );
00291 
00292 
00293 // for LuaClassObjRef:
00294 
00295 DEF_FN_CALL_1(LuaClassObjRef::callMethod, prepCall(arg1).doCall() );
00296 DEF_FN_CALL_2(LuaClassObjRef::callMethod, ( prepCall(arg1) << arg2 ).doCall() );
00297 DEF_FN_CALL_3(LuaClassObjRef::callMethod, ( prepCall(arg1) << arg2 << arg3 ).doCall() );
00298 DEF_FN_CALL_4(LuaClassObjRef::callMethod, ( prepCall(arg1) << arg2 << arg3 << arg4 ).doCall() );
00299 DEF_FN_CALL_5(LuaClassObjRef::callMethod, ( prepCall(arg1) << arg2 << arg3 << arg4 << arg5 ).doCall() );
00300 DEF_FN_CALL_6(LuaClassObjRef::callMethod, ( prepCall(arg1) << arg2 << arg3 << arg4 << arg5 << arg6 ).doCall() );
00301 DEF_FN_CALL_7(LuaClassObjRef::callMethod, ( prepCall(arg1) << arg2 << arg3 << arg4 << arg5 << arg6 << arg7 ).doCall() );
00302 DEF_FN_CALL_8(LuaClassObjRef::callMethod, ( prepCall(arg1) << arg2 << arg3 << arg4 << arg5 << arg6 << arg7 << arg8 ).doCall() );
00303 DEF_FN_CALL_9(LuaClassObjRef::callMethod, ( prepCall(arg1) << arg2 << arg3 << arg4 << arg5 << arg6 << arg7 << arg8 << arg9 ).doCall() );
00304 
00305 
00306 #endif // LUA_ICXX_FUNCREF_INCLUDED