|
QLua
Lua-Qt bindings
|
00001 #pragma once 00002 // QLua - Copyright (c) 2012, Ugo Varetto 00003 // All rights reserved. 00004 // 00005 // Redistribution and use in source and binary forms, with or without 00006 // modification, are permitted provided that the following conditions are met: 00007 // * Redistributions of source code must retain the above copyright 00008 // notice, this list of conditions and the following disclaimer. 00009 // * Redistributions in binary form must reproduce the above copyright 00010 // notice, this list of conditions and the following disclaimer in the 00011 // documentation and/or other materials provided with the distribution. 00012 // * Neither the name of the <organization> nor the 00013 // names of its contributors may be used to endorse or promote products 00014 // derived from this software without specific prior written permission. 00015 // 00016 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00017 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00018 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00019 // DISCLAIMED. IN NO EVENT SHALL UGO VARETTO BE LIABLE FOR ANY 00020 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00021 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00022 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00023 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00024 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00025 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 00029 00030 extern "C" { 00031 #include "lua.h" 00032 #include "lauxlib.h" 00033 #include "lualib.h" 00034 } 00035 00036 #include <stdexcept> 00037 #include <string> 00038 00039 #include <QMetaMethod> 00040 #include <QString> 00041 #include <QMap> 00042 #include <QList> 00043 #include <QStringList> 00044 00045 #include "LuaCallbackDispatcher.h" 00046 #include "LuaArguments.h" 00047 #include "LuaQtTypes.h" 00048 #include "ILuaSignatureMapper.h" 00049 00050 #define QLUA_VERSION "0.2" 00051 #define QLUA_VERSION_MAJ 0 00052 #define QLUA_VERSION_MIN 2 00053 00054 namespace qlua { 00055 00056 inline void RaiseLuaError( lua_State* L, const char* errMsg ) { 00057 lua_pushstring( L, errMsg ); 00058 lua_error( L ); 00059 } 00060 inline void RaiseLuaError( lua_State* L, const QString& errMsg ) { 00061 RaiseLuaError( L, errMsg.toAscii().constData() ); 00062 } 00063 inline void RaiseLuaError( lua_State* L, const std::string& errMsg ) { 00064 RaiseLuaError( L, errMsg.c_str() ); 00065 } 00066 00068 struct LuaDefaultSignatureMapper : ILuaSignatureMapper { 00072 QString map( const QString& sig ) const { 00073 QString name = sig; 00074 name.truncate( sig.indexOf( "(" ) ); 00075 return name; 00076 } 00077 }; 00078 00079 00080 //------------------------------------------------------------------------------ 00088 class LuaContext { 00095 struct Method { 00096 QObject* obj_; 00097 QMetaMethod metaMethod_; 00098 QArgWrappers argumentWrappers_; 00099 LArgWrapper returnWrapper_; 00100 Method( QObject* obj, const QMetaMethod& mm, const QArgWrappers& pw, const LArgWrapper& rw ) : 00101 obj_( obj ), metaMethod_( mm ), argumentWrappers_( pw ), returnWrapper_( rw ) {} 00102 }; 00103 public: 00105 enum ObjectDeleteMode { 00106 QOBJ_NO_DELETE, 00107 QOBJ_IMMEDIATE_DELETE, 00108 QOBJ_DELETE_LATER 00109 }; 00110 typedef QList< Method > Methods; 00111 typedef QMap< QObject*, QMap< QString, Methods > > ObjectMethodMap; 00112 typedef QMap< QObject*, int > ObjectReferenceMap; 00115 LuaContext( lua_State* L = 0 ); 00117 lua_State* LuaState() const { return L_; } 00119 void Eval( const char* code ) { 00120 ReportErrors( luaL_dostring( L_, code ) ); 00121 } 00125 void AddQVariantMap( const QVariantMap& vm, const char* name = 0 ) { 00126 VariantMapToLuaTable( vm, L_ ); 00127 if( name ) lua_setglobal( L_, name ); 00128 } 00132 void AddQVariantList( const QVariantList& vl, const char* name = 0 ) { 00133 VariantListToLuaTable( vl, L_ ); 00134 if( name ) lua_setglobal( L_, name ); 00135 } 00139 void AddQStringList( const QStringList& sl, const char* name = 0 ){ 00140 StringListToLuaTable( sl, L_ ); 00141 if( name ) lua_setglobal( L_, name ); 00142 } 00146 template < typename T > void AddQList( const QList< T >& l, const char* name = 0 ) { 00147 NumberListToLuaTable< T >( l, L_ ); 00148 if( name ) lua_setglobal( L_, name ); 00149 } 00168 void AddQObject( QObject* obj, 00169 const char* tableName = 0, 00170 bool cache = false, 00171 ObjectDeleteMode deleteMode = QOBJ_NO_DELETE, 00172 const ILuaSignatureMapper& mapper = LuaDefaultSignatureMapper(), 00173 const QStringList& methodNames = QStringList(), 00174 const QList< QMetaMethod::MethodType >& methodTypes = 00175 QList< QMetaMethod::MethodType >() ); 00181 bool OwnQObjects() const { return ownQObjects_; } 00183 ~LuaContext() { 00184 if( !wrappedContext_ ) lua_close( L_ ); 00185 } 00186 private: 00188 void RemoveObject( QObject* obj ); 00190 00191 00192 static int QtConnect( lua_State* L ); 00194 static int QtDisconnect( lua_State* L ); 00199 static int InvokeMethod( lua_State* L ); 00201 static int DeleteObject( lua_State* L ); 00203 static int SetQObjectsOwnership( lua_State* L ); 00205 00206 00207 00208 static int Invoke0( const Method* mi, LuaContext& L ); 00209 static int Invoke1( const Method* mi, LuaContext& L ); 00210 static int Invoke2( const Method* mi, LuaContext& L ); 00211 static int Invoke3( const Method* mi, LuaContext& L ); 00212 static int Invoke4( const Method* mi, LuaContext& L ); 00213 static int Invoke5( const Method* mi, LuaContext& L ); 00214 static int Invoke6( const Method* mi, LuaContext& L ); 00215 static int Invoke7( const Method* mi, LuaContext& L ); 00216 static int Invoke8( const Method* mi, LuaContext& L ); 00217 static int Invoke9( const Method* mi, LuaContext& L ); 00218 static int Invoke10( const Method* mi, LuaContext& L ); 00220 00221 void ReportErrors( int status ) { 00222 if( status != 0 ) { 00223 std::string err = lua_tostring( L_, -1 ); 00224 lua_pop( L_, 1 ); 00225 throw std::runtime_error( err ); 00226 } 00227 } 00229 static void RegisterTypes(); 00230 private: 00232 lua_State* L_; 00234 bool wrappedContext_; 00236 bool ownQObjects_; 00239 ObjectMethodMap objMethods_; 00241 ObjectReferenceMap objRefs_; 00247 LuaCallbackDispatcher dispatcher_; 00248 }; 00249 00250 00255 template < typename T > 00256 T GetValue( const LuaContext& lc, const QString& name ) { 00257 lua_getglobal( lc.LuaState(), name.toAscii().constData() ); 00258 return luaL_checknumber( lc.LuaState(), -1 ); 00259 } 00260 00262 template < typename T > 00263 QList< T > GetValues( const LuaContext& lc, const QString& name ) { 00264 if( !lua_istable( lc.LuaState(), -1 ) ) throw std::runtime_error( "Not a lua table" ); 00265 return ParseLuaTableAsNumberList< T >( lc.LuaState(), -1 ); 00266 } 00267 00269 template <> 00270 inline QString GetValue< QString >( const LuaContext& lc, const QString& name ) { 00271 lua_getglobal( lc.LuaState(), name.toAscii().constData() ); 00272 return luaL_checkstring( lc.LuaState(), -1 ); 00273 } 00274 00276 template <> 00277 inline QVariantMap GetValue< QVariantMap >( const LuaContext& lc, const QString& name ) { 00278 lua_getglobal( lc.LuaState(), name.toAscii().constData() ); 00279 if( !lua_istable( lc.LuaState(), -1 ) ) throw std::runtime_error( "Not a lua table" ); 00280 return ParseLuaTable( lc.LuaState(), -1 ); 00281 } 00282 00284 template <> 00285 inline QVariantList GetValue< QVariantList >( const LuaContext& lc, const QString& name ) { 00286 lua_getglobal( lc.LuaState(), name.toAscii().constData() ); 00287 if( !lua_istable( lc.LuaState(), -1 ) ) throw std::runtime_error( "Not a lua table" ); 00288 return ParseLuaTableAsVariantList( lc.LuaState(), -1 ); 00289 } 00290 00292 template <> 00293 inline QStringList GetValue< QStringList >( const LuaContext& lc, const QString& name ) { 00294 lua_getglobal( lc.LuaState(), name.toAscii().constData() ); 00295 if( !lua_istable( lc.LuaState(), -1 ) ) throw std::runtime_error( "Not a lua table" ); 00296 return ParseLuaTableAsStringList( lc.LuaState(), -1 ); 00297 } 00298 00299 }
1.7.4