QLua
Lua-Qt bindings
LuaContext.h
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Enumerations Enumerator