From: John L. <jr...@us...> - 2005-11-25 02:47:01
|
Update of /cvsroot/wxlua/wxLua/modules/wxlua/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26103/wxLua/modules/wxlua/src Added Files: wxlbind.cpp wxlcallb.cpp wxlhandl.cpp wxlintrp.cpp wxlstate.cpp Log Message: added replacements for interp, callback - breaking up internal --- NEW FILE: wxlstate.cpp --- ///////////////////////////////////////////////////////////////////////////// // Purpose: Interface to wxLua // Author: Ray Gilbert, John Labenski, J Winwood // Created: 14/11/2001 // Copyright: (c) 2001-2002 Lomtick Software. All rights reserved. // Licence: wxWidgets licence ///////////////////////////////////////////////////////////////////////////// #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "wxlstate.h" #endif // For compilers that support precompilation, includes <wx/wx.h>. #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif // for all others, include the necessary headers #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "wxlua/include/wxlstate.h" #include "wxlua/include/wxlcallb.h" #include "wxbind/include/wxbind.h" extern bool wxLuaCleanupWindows(wxList *list, bool only_check); // in interp.cpp extern int wxLuaEventListCompareFn(const void *p1, const void *p2); // in wxlbind.cpp extern int wxLuaClassListCompareByTag(const void *p1, const void *p2); // in wxlbind.cpp const char *wxLuaReferences; // in internal.cpp //---------------------------------------------------------------------------- // wxLuaStateRefData //---------------------------------------------------------------------------- wxHashMapLuaState wxLuaStateRefData::s_wxHashMapLuaState; void wxLuaStateRefData::Init() { m_lua_State = NULL; m_typesRegistered = false; m_startTag = 0; m_lastTag = 0; m_functionTag = 0; m_wxLuaTable = 0; m_wxLuaNull = 0; m_wxDeleteTable = 0; m_inEventType = -1; m_pDerivedList = new wxHashTable(wxKEY_INTEGER); m_pTrackedList = new wxHashTable(wxKEY_INTEGER); m_pAppHandlerList = new wxList; m_pDestroyHandlerList = new wxList; m_pWindowList = new wxList; } wxLuaStateRefData::wxLuaStateRefData() { Init(); } wxLuaStateRefData::wxLuaStateRefData( const wxLuaStateRefData& data ) { } wxLuaStateRefData::~wxLuaStateRefData() { // remove deleted windows first if (m_pWindowList && m_pWindowList->GetCount()) wxLuaCleanupWindows(m_pWindowList, true); // are there still windows? ask to abort deleting them if !force if (m_pWindowList && m_pWindowList->GetCount()) { /* int ret = wxOK; //if (!force) { ret = wxMessageBox(wxT("Windows are still open, would you like to delete them?"), wxT("Delete existing windows?"), wxOK|wxCANCEL|wxICON_QUESTION); } if (ret == wxCANCEL) return FALSE; */ //wxPrintf(wxT("Deleting windows\n")); // delete windows and their eventhandler since they delete the LuaCallbacks // which require a lua_State wxLuaCleanupWindows(m_pWindowList, FALSE); // wait for wxWindow::Destroy() to really delete the windows //wxYieldIfNeeded(); } CleanupWxLua(m_lua_State, true); s_wxHashMapLuaState.erase(m_lua_State); ClearCallbacks(); delete m_pDerivedList; delete m_pTrackedList; delete m_pAppHandlerList; delete m_pDestroyHandlerList; delete m_pWindowList; } void wxLuaStateRefData::ClearCallbacks() { // remove any and all callbacks that use this event handler since its gone wxNode* node = m_pAppHandlerList->GetFirst(); while (node) { wxLuaCallback *pCallback = (wxLuaCallback *) node->GetData(); if (pCallback) { pCallback->ClearState(); pCallback->ClearStateVars(); } node = node->GetNext(); } node = m_pDestroyHandlerList->GetFirst(); while (node) { wxLuaDestroyCallback *pCallback = (wxLuaDestroyCallback *) node->GetData(); if (pCallback) { pCallback->ClearState(); pCallback->ClearStateVars(); } node = node->GetNext(); } // don't "own" pointers to wxLuaCallbacks, let wxEventHandler do it m_pAppHandlerList->DeleteContents(false); // don't delete wxLuaDestroyCallbacks, let wxEventHandler do it m_pDestroyHandlerList->DeleteContents(false); } //---------------------------------------------------------------------------- // wxLuaState //---------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxLuaState, wxObject) #define M_WXLSTATEDATA ((wxLuaStateRefData*)m_refData) wxObjectRefData *wxLuaState::CreateRefData() const { return new wxLuaStateRefData; } wxObjectRefData *wxLuaState::CloneRefData(const wxObjectRefData *data) const { return new wxLuaStateRefData(*(const wxLuaStateRefData *)data); } void LUACALL wxLuaState::RegisterBindings(bool registerTypes) { wxCHECK_RET(Ok(), wxT("Invalid wxLuaState")); lua_State* L = M_WXLSTATEDATA->m_lua_State; wxCHECK_RET(L, wxT("Invalid wxLuaState")); // create references table in registry lua_pushstring(L, wxLuaReferences); lua_newtable(L); lua_rawset(L, LUA_REGISTRYINDEX); // Register bindings wxLuaBindingList::Node *node; for (node = M_WXLSTATEDATA->m_bindings.GetFirst(); node; node = node->GetNext() ) { wxLuaBinding* binding = node->GetData(); binding->RegisterBinding(L, registerTypes); } M_WXLSTATEDATA->m_typesRegistered = true; // setup base class tags for (node = M_WXLSTATEDATA->m_bindings.GetFirst(); node; node = node->GetNext() ) { wxLuaBinding* binding = node->GetData(); WXLUACLASS* pClass = (WXLUACLASS *)binding->GetLuaClassList(); for (size_t i = 0; i < binding->GetLuaClassCount(); i++) { WXLUACLASS* pLuaClass = pClass + i; pLuaClass->baseclass_tag = -1; if (pLuaClass->baseclass) { wxLuaBindingList::Node* basenode; for (basenode = M_WXLSTATEDATA->m_bindings.GetFirst(); basenode; basenode = basenode->GetNext() ) { wxLuaBinding* basebinding = basenode->GetData(); // found base class in binding? if (basebinding->SetBaseClassTag(pLuaClass)) break; } } } } // register our 'function' object handlers if (registerTypes) { M_WXLSTATEDATA->m_functionTag = tnewtag(L); M_WXLSTATEDATA->m_wxDeleteTable = tnewweaktag(L, false, true); } tsettagmethod (L, M_WXLSTATEDATA->m_functionTag, "__gc", functionGarbageCollect); tsettagmethod (L, M_WXLSTATEDATA->m_functionTag, "__call", callFunction); } void LUACALL wxLuaState::UnRegisterBindings() { wxCHECK_RET(Ok(), wxT("Invalid wxLuaState")); lua_State* L = M_WXLSTATEDATA->m_lua_State; wxCHECK_RET(L, wxT("Invalid wxLuaState")); // UnRegister bindings wxLuaBindingList::Node *node; for (node = M_WXLSTATEDATA->m_bindings.GetFirst(); node; node = node->GetNext() ) { wxLuaBinding* binding = node->GetData(); binding->UnRegisterBinding(L); } lua_pushstring(L, wxLuaReferences); lua_pushnil(L); lua_rawset(L, LUA_REGISTRYINDEX); } // Find binding with given nameSpace wxLuaBinding* wxLuaState::GetLuaBinding(const wxString& nameSpace) { wxLuaBindingList::Node *node; for (node = M_WXLSTATEDATA->m_bindings.GetFirst(); node; node = node->GetNext() ) { wxLuaBinding* binding = node->GetData(); if (binding->nameSpace == nameSpace) return binding; } return NULL; } // Get WXLUACLASS for given Tag const WXLUACLASS* wxLuaState::GetLuaClass(int iClassTag) { WXLUACLASS classItem; classItem.class_tag = &iClassTag; wxLuaBindingList::Node *node; for (node = M_WXLSTATEDATA->m_bindings.GetFirst(); node; node = node->GetNext() ) { wxLuaBinding* binding = node->GetData(); // this relies on LUA allocating tags in ascending order of definition // if LUA stops doing this, then the search may break. const WXLUACLASS *pLuaClass = (WXLUACLASS *) bsearch(&classItem, binding->GetLuaClassList(), binding->GetLuaClassCount(), sizeof(WXLUACLASS), wxLuaClassListCompareByTag); // found if (pLuaClass) return pLuaClass; } return NULL; } // Get WXLUACLASS for given class name const WXLUACLASS* wxLuaState::GetLuaClass(const char* className) { wxLuaBindingList::Node *node; for (node = M_WXLSTATEDATA->m_bindings.GetFirst(); node; node = node->GetNext() ) { wxLuaBinding* binding = node->GetData(); WXLUACLASS *pLuaClass = (WXLUACLASS *)binding->GetLuaClassList(); for (size_t i = 0; i < binding->GetLuaClassCount(); i++) { if (strcmp(pLuaClass->name, className) == 0) return pLuaClass; pLuaClass++; } } return NULL; } // Get base WXLUACLASS for given Tag const WXLUACLASS* wxLuaState::GetBaseLuaClass(int iClassTag) { const WXLUACLASS *pLuaClass = GetLuaClass(iClassTag); if (pLuaClass && pLuaClass->baseclass_tag != -1) return GetLuaClass(pLuaClass->baseclass_tag); return NULL; } // returns true is iClassTag is derived from iBaseClassTag bool wxLuaState::IsDerivedClass(int iClassTag, int iBaseClassTag) { if (iClassTag == iBaseClassTag) return true; const WXLUACLASS *pLuaClass = GetLuaClass(iClassTag); if (pLuaClass && pLuaClass->baseclass_tag != -1) return IsDerivedClass(pLuaClass->baseclass_tag, iBaseClassTag); return false; } // Get WXLUAEVENT for given wxEvent const WXLUAEVENT* wxLuaState::GetLuaEvent(wxEvent *pEvent) { WXLUAEVENT eventItem; int eventType = pEvent->GetEventType(); eventItem.eventType = &eventType; wxLuaBindingList::Node *node; for (node = M_WXLSTATEDATA->m_bindings.GetFirst(); node; node = node->GetNext() ) { wxLuaBinding* binding = node->GetData(); WXLUAEVENT *pLuaEvent = (WXLUAEVENT *) bsearch(&eventItem, binding->GetLuaEventList(), binding->GetLuaEventCount(), sizeof(WXLUAEVENT), wxLuaEventListCompareFn); // found if (pLuaEvent) return pLuaEvent; } return NULL; } --- NEW FILE: wxlbind.cpp --- ///////////////////////////////////////////////////////////////////////////// // Purpose: wxLuaBinding // Author: Ray Gilbert, John Labenski, J Winwood // Created: 14/11/2001 // Copyright: // Licence: wxWidgets licence ///////////////////////////////////////////////////////////////////////////// #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "wxlbind.h" #endif #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #include "wx/app.h" #endif #include "wx/datetime.h" #include "../../../bindings/wxwidgets/luasetup.h.in" // get the base library setup parameters #include "wxlua/include/internal.h" #include "wxlua/include/wxlcallb.h" #include "wxlua/include/wxlbind.h" #include "wxbind/include/wxbind.h" #include "wxlua/include/wxlintrp.h" #include "wx/listimpl.cpp" WX_DEFINE_LIST(wxLuaBindingList); static int LUACALL wxLuaTableErrorHandler(lua_State *L) { terror(L, "Cannot modify read-only wxLua table"); return 0; } // Function to compare to events by eventType int wxLuaEventListCompareFn(const void *p1, const void *p2) { return (*((const WXLUAEVENT *) p1)->eventType) - (*((const WXLUAEVENT *) p2)->eventType); } // ---------------------------------------------------------------------------- // wxLuaBinding // ---------------------------------------------------------------------------- IMPLEMENT_CLASS(wxLuaBinding, wxObject) wxLuaBinding::wxLuaBinding() : wxObject(), pfGetClassList(NULL), pfGetDefineList(NULL), pfGetEventList(NULL), pfGetObjectList(NULL), pfGetBuiltinList(NULL), m_classCount(0), m_classList(NULL), m_defineCount(0), m_defineList(NULL), m_eventCount(0), m_eventList(NULL), m_objectCount(0), m_objectList(NULL), m_builtinCount(0), m_builtinList(NULL), m_typesRegistered(false), m_startTag(0), m_lastTag(0), m_wxLuaTable(0) { } void wxLuaBinding::RegisterBinding(lua_State *L, bool registerTypes) { int luaTable = RegisterFunctions(L, registerTypes); // create a global lua_pushstring(L, wx2lua(nameSpace)); lua_pushvalue(L, luaTable); lua_rawset(L, LUA_GLOBALSINDEX); lua_pop(L, 1); } void wxLuaBinding::UnRegisterBinding(lua_State *L) { lua_pushstring(L, wx2lua(nameSpace)); lua_pushnil(L); lua_rawset(L, LUA_GLOBALSINDEX); } int LUACALL wxLuaBinding::RegisterFunctions(lua_State *L, bool registerTypes) { GET_LUASTATEVARS_MSG(L, 0) if (!registerTypes && !m_typesRegistered) terror(L, "wxLua: First time registration must register types"); // create references table in registry // lua_pushstring(L, wxLuaReferences); // lua_newtable(L); // lua_rawset(L, LUA_REGISTRYINDEX); // create a tag for the wxLua table if (registerTypes) m_wxLuaTable = tnewtag(L); // create the wxLua table lua_newtable(L); int tableOffset = lua_gettop(L); // set the table tag tsettag (L, m_wxLuaTable); // prevent changes from lua scripts tsettagmethod (L, m_wxLuaTable, "__newindex", wxLuaTableErrorHandler); // register all out classes etc. in the wxLua table RegisterGeneratedClasses(L, tableOffset, registerTypes); OnRegister(L, registerTypes, tableOffset); m_typesRegistered = true; return tableOffset; } void LUACALL wxLuaBinding::RegisterGeneratedClasses(lua_State *L, int tableOffset, bool registerTypes) { GET_LUASTATEVARS_RET(L) static const luaL_reg funcTable[] = { {"__gc", garbageCollect }, {"__index", getTableFunc }, {"__newindex", setTableFunc } }; const unsigned funcCount = sizeof(funcTable)/sizeof(funcTable[0]); size_t iClass; if (registerTypes) m_startTag = tnewtag(L); int iTag = m_startTag; // install the classes, functions and methods m_classList = (*pfGetClassList)(m_classCount); for (iClass = 0; iClass < m_classCount; ++iClass, iTag = registerTypes ? tnewtag(L) : iTag + 1) { WXLUACLASS *pClass = m_classList + iClass; *pClass->class_tag = iTag; //wxPrintf(wxT("RegisterGenClasses %d '%s'\n"), iTag, lua2wx(pClass->name).c_str()); for (unsigned iFunction = 0; iFunction < funcCount; iFunction++) { tsettagmethod (L, iTag, funcTable[iFunction].name, funcTable[iFunction].func, (void *) pClass); } for (int iMethod = 0; iMethod < pClass->num_methods; ++iMethod) { WXLUAMETHOD *pMethod = pClass->methods + iMethod; if ((pMethod->type == LuaConstructor) || (pMethod->type == LuaGlobal)) { lua_pushstring(L, pMethod->name); lua_pushcfunction(L, pMethod->func); lua_rawset(L, tableOffset); } } } m_lastTag = iTag; // register all the builtin functions m_builtinList = (*pfGetBuiltinList)(m_builtinCount); for (size_t iBuiltin= 0; iBuiltin < m_builtinCount; ++iBuiltin) { WXLUAMETHOD *pMethod = m_builtinList + iBuiltin; lua_pushstring(L, pMethod->name); lua_pushcfunction(L, pMethod->func); lua_rawset(L, tableOffset); } // for backward compatibility lua_pushliteral(L, "FALSE"); lua_pushboolean(L, false); lua_rawset(L, tableOffset); lua_pushliteral(L, "TRUE"); lua_pushboolean(L, true); lua_rawset(L, tableOffset); // install the definitions and strings m_defineList = (*pfGetDefineList)(m_defineCount); for (size_t iDefine = 0; iDefine < m_defineCount; ++iDefine) { WXLUADEFINE *pDefine = m_defineList + iDefine; lua_pushstring(L, pDefine->name); if (pDefine->isString) lua_pushstring(L, wx2lua(pDefine->strValue)); else lua_pushnumber(L, pDefine->value); lua_rawset(L, tableOffset); } // install the objects and pointers m_objectList = (*pfGetObjectList)(m_objectCount); for (size_t iObject = 0; iObject < m_objectCount; ++iObject) { WXLUAOBJECT *pObject = m_objectList + iObject; lua_pushstring(L, pObject->objName); if (pObject->objPtr != 0) tpushusertag(L, pObject->objPtr, *pObject->objClassTag); else tpushusertag(L, *pObject->pObjPtr, *pObject->objClassTag); lua_rawset(L, tableOffset); } // register all the event types m_eventList = (*pfGetEventList)(m_eventCount); for (size_t iEvent = 0; iEvent < m_eventCount; ++iEvent) { WXLUAEVENT *pEvent = m_eventList + iEvent; lua_pushstring(L, pEvent->eventName); lua_pushnumber(L, *pEvent->eventType); lua_rawset(L, tableOffset); } // sort the event list into order for faster lookup. qsort(m_eventList, m_eventCount, sizeof(WXLUAEVENT), wxLuaEventListCompareFn); } bool wxLuaBinding::SetBaseClassTag(WXLUACLASS *pClass) { if (!pClass->baseclass) return false; if (!m_classList) return false; // install the classes, functions and methods for (size_t i = 0; i < m_classCount; ++i) { WXLUACLASS* baseClass = m_classList + i; if (strcmp(baseClass->name, pClass->baseclass) == 0) { pClass->baseclass_tag = *baseClass->class_tag; return true; } } return false; } --- NEW FILE: wxlintrp.cpp --- ///////////////////////////////////////////////////////////////////////////// // Name: wxLuaInterpreter // Purpose: A simple class for a C++ wxWidgets program to embed wxLua // Author: John Labenski // Modified by: // Created: 11/05/2002 // RCS-ID: // Copyright: (c) John Labenki // Licence: wxWidgets licence ///////////////////////////////////////////////////////////////////////////// // references // http://www.andreas-rozek.de/Lua/index_en.html interesing libraries perhaps #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "wxlintrp.h" #endif // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif // WX_PRECOMP #include "wxlua/include/wxlintrp.h" #include "wxlua/include/internal.h" extern int s_wxLuaInterpreter; wxHashMapLuaInterpreter s_wxHashMapLuaInterpreter; // add lua_States created from lua's coroutines #define WXLUA_THREAD_INTERCEPTION extern "C" { #include "lua/include/lua.h" #include "lua/include/lauxlib.h" #include "lua/include/lualib.h" #ifdef WXLUA_THREAD_INTERCEPTION // See lua/src/lstate.c for added hook into luaE_newthread() #include "lua/include/luathread.h" #endif //WXLUA_THREAD_INTERCEPTION } #ifdef WXLUA_THREAD_INTERCEPTION // Hook into function calls to luaE_newthread (calls from coroutine.create/wrap) // and add the new lua_State as a child sharing it's wxLuaStateVariables void wxLuaInterpreter_newthread_handler(lua_State *L, lua_State *L1) { // L is the original lua_State, L1 new child thread wxLuaInterpreter *L_interp = wxFindLuaInterpreter(L); //printf("Adding new lua_State from a thread L=%ld L1=%ld\n", (long)L, (long)L1); fflush(stdout); if (L_interp != NULL) s_wxHashMapLuaInterpreter[L1] = L_interp; } // Hook into function calls to luaE_freethread (calls from coroutine.create/wrap) // and remove the child lua_State void wxLuaInterpreter_freethread_handler(lua_State *WXUNUSED(L), lua_State *L1) { // L is the original lua_State, L1 child thread, don't remove L //printf("Freeing lua_State from a thread L=%ld L1=%ld\n", (long)L, (long)L1); fflush(stdout); s_wxHashMapLuaInterpreter.erase(L1); } static void setupthreadhandlers() { if (luaX_getnewthreadhandler() == NULL) luaX_setnewthreadhandler( wxLuaInterpreter_newthread_handler ); if (luaX_getfreethreadhandler() == NULL) luaX_setfreethreadhandler( wxLuaInterpreter_freethread_handler ); } #endif //WXLUA_THREAD_INTERCEPTION // ---------------------------------------------------------------------------- // Extra wxLua helpers that use the lua_State to find owner wxLuaInterpreter // ---------------------------------------------------------------------------- wxLuaInterpreter *wxFindLuaInterpreter(lua_State *L) { int top = lua_gettop( L ); // try to get the state lua_pushstring( L, "__wxLuaInterpreter" ); lua_gettable( L, LUA_REGISTRYINDEX ); // if nothing was returned or it wasn't a ptr, abort if ( top == lua_gettop(L) || !lua_islightuserdata(L, -1) ) { lua_settop( L, top ); return NULL; } // get the pointer, clean the stack, return wxLuaInterpreter* lI = (wxLuaInterpreter*)lua_touserdata( L, -1 ); lua_settop( L, top ); return lI; } wxLuaStateVariables *wxFindLuaStateVariables(lua_State *L) { wxLuaInterpreter *luaInterpreter = wxFindLuaInterpreter(L); if (luaInterpreter && luaInterpreter->Ok()) return luaInterpreter->GetStateVariables(); return NULL; } // ---------------------------------------------------------------------------- // wxFindWindowByPointer - find a window by it's pointer // return NULL if doesn't exist, see wxFindWindowByID and wxFindWindowByLabel // ---------------------------------------------------------------------------- static wxWindow *wxFindWindowPointerRecursively(const wxWindow *parent, const wxWindow *win) { wxCHECK_MSG(win, NULL, wxT("invalid window in wxFindWindowPointerRecursively")); if ( parent ) { // see if this is the one we're looking for if ( parent == win ) return (wxWindow*)win; // It wasn't, so check all its children for ( wxWindowList::Node * node = parent->GetChildren().GetFirst(); node; node = node->GetNext() ) { // recursively check each child wxWindow *child_win = (wxWindow *)node->GetData(); wxWindow *retwin = wxFindWindowPointerRecursively(child_win, win); if (retwin) return retwin; } } // Not found return NULL; } // Check to see if wxWidgets still thinks "win" is a valid window // parent is the window to start with, if parent=NULL check all windows static wxWindow* wxFindWindowByPointer(const wxWindow *parent, const wxWindow *win) { wxCHECK_MSG(win, NULL, wxT("Invalid window in wxFindWindowByPointer")); if ( parent ) { // just check parent and all its children return wxFindWindowPointerRecursively(parent, win); } // start at very top of wx's windows for ( wxWindowList::Node * top_node = wxTopLevelWindows.GetFirst(); top_node; top_node = top_node->GetNext() ) { // recursively check each window & its children wxWindow *top_win = top_node->GetData(); wxWindow *retwin = wxFindWindowPointerRecursively(top_win, win); if (retwin) return retwin; } return NULL; } // ---------------------------------------------------------------------------- // wxLuaCleanupWindows - given a wxList of wxWindows it runs wxFindWindowByPointer // on it to remove dead pointers from the list if only_check=TRUE or // Destroy() the windows and remove them from the list if !only_check. // This is for use with wxLuaStateVariables::m_pWindowList. // returns TRUE if any windows removed, ie. the list has changed // ---------------------------------------------------------------------------- bool wxLuaCleanupWindows(wxList *list, bool only_check) { bool removed = FALSE; wxNode *node = list->GetFirst(); while (node != NULL) { wxWindow *win = (wxWindow *)node->GetData(); if (!win) { wxNode *lastNode = node; node = node->GetNext(); list->DeleteNode(lastNode); } else if (wxFindWindowByPointer(NULL, win) == NULL) { removed = TRUE; wxNode *lastNode = node; node = node->GetNext(); //printf("%d %d\n", int(lastNode), int(node)); fflush(stdout); list->DeleteNode(lastNode); } else if (!only_check) { removed = TRUE; if (win->HasCapture()) win->ReleaseMouse(); // release capture for children since we may be abruptly ending for ( wxWindowList::compatibility_iterator childNode = win->GetChildren().GetFirst(); childNode; childNode = childNode->GetNext() ) { wxWindow *child = childNode->GetData(); list->DeleteObject(child); if (child->HasCapture()) child->ReleaseMouse(); } if (!win->IsBeingDeleted()) { delete win; } // wxLuaWindowDestroyHandler should destroy this node // and also delete all the children and their nodes // it's probably best to start from the top again list->DeleteObject(win); //wxPrintf(wxT("%d %d\n"), int(1), int(win)); fflush(stdout); node = list->GetFirst(); } else node = node->GetNext(); } return removed; } // ---------------------------------------------------------------------------- // lua hooks and function replacements for embedding into wxWidgets // ---------------------------------------------------------------------------- int LuaPrint( lua_State *L ) { wxString msg; int i, n = lua_gettop(L); // figure out the types here in c++ land lua_getglobal(L, "tostring"); for (i = 1; i <= n; i++) { if (i > 1) msg.Append(wxT(", ")); if (lua_isstring(L, i)) msg += lua2wx(lua_tostring(L, i)); else if (lua_isnumber(L, i)) msg += wxString::Format(wxT("%lf"), lua_tonumber(L, i)); else if (lua_iscfunction(L, i)) msg += wxString::Format(wxT("C function %ld"), (long int)lua_tocfunction(L, i)); else if (lua_isuserdata(L, i)) msg += wxString::Format(wxT("User data %ld"), (long int)lua_touserdata(L, i)); else if (lua_isboolean(L, i)) msg += lua_toboolean(L,i) ? wxT("true") : wxT("false"); else if (lua_isnil(L,i)) msg += wxT("nil"); else if (lua_isnone(L,i)) msg += wxT("unknown"); else msg += wxString::Format(wxT("%s:%p"), lua_typename(L,lua_type(L,i)), lua_topointer(L,i)); } if (!msg.IsEmpty()) { wxLuaInterpreter *luaInterpreter = wxFindLuaInterpreter(L); if (luaInterpreter) { wxLuaEvent event(wxEVT_LUA_CONSOLE, luaInterpreter->GetId(), luaInterpreter); event.SetString(msg); luaInterpreter->SendEvent( event ); } } return 0; // no items put onto stack } // copied from the Lua 5.0.1 debug library #define LEVELS1 12 /* size of the first part of the stack */ #define LEVELS2 10 /* size of the second part of the stack */ // copied from the Lua 5.0.1 debug library int LuaTraceback(lua_State *L) { int level = 1; // skip level 0 (it's this function) int firstpart = 1; // still before eventual `...' lua_Debug ar; if (lua_gettop(L) == 0) lua_pushliteral(L, ""); else if (!lua_isstring(L, 1)) // no string message return 1; else lua_pushliteral(L, "\n"); lua_pushliteral(L, "stack traceback:"); while (lua_getstack(L, level++, &ar)) { if (level > LEVELS1 && firstpart) { // no more than `LEVELS2' more levels? if (!lua_getstack(L, level+LEVELS2, &ar)) level--; // keep going else { lua_pushliteral(L, "\n\t..."); // too many levels while (lua_getstack(L, level+LEVELS2, &ar)) // find last levels level++; } firstpart = 0; continue; } lua_pushliteral(L, "\n\t"); lua_getinfo(L, "Snl", &ar); lua_pushfstring(L, "%s:", ar.short_src); if (ar.currentline > 0) lua_pushfstring(L, "%d:", ar.currentline); switch (*ar.namewhat) { case 'g': // global case 'l': // local case 'f': // field case 'm': // method lua_pushfstring(L, " in function `%s'", ar.name); break; default: { if (*ar.what == 'm') // main? lua_pushfstring(L, " in main chunk"); else if (*ar.what == 'C' || *ar.what == 't') lua_pushliteral(L, " ?"); // C function or tail call else lua_pushfstring(L, " in function <%s:%d>", ar.short_src, ar.linedefined); } } lua_concat(L, lua_gettop(L)); } lua_concat(L, lua_gettop(L)); return 1; } int LuaAlert( lua_State *L ) { wxLuaInterpreter *luaInterpreter = wxFindLuaInterpreter(L); if (luaInterpreter) { wxString msg = lua2wx(lua_tostring(L, 1)); wxLuaEvent event(wxEVT_LUA_ERROR, luaInterpreter->GetId(), luaInterpreter); event.SetString(msg); long line = -1; wxString lineStr = msg; // Why can't I fill a lua_Debug here? Try to get the line number // by parsing the error message that looks like this, 1 is linenumber // [string "a = 1("]:1: unexpected symbol near `<eof>' while(!lineStr.IsEmpty()) { lineStr = lineStr.AfterFirst(wxT(']')); if ((lineStr.Length() > 0) && (lineStr.GetChar(0) == wxT(':'))) { lineStr = lineStr.AfterFirst(wxT(':')); if (lineStr.IsEmpty() || lineStr.BeforeFirst(wxT(':')).ToLong(&line)) break; } } event.SetInt((int)line); luaInterpreter->SendEvent( event ); } return 0; } void LuaDebugHook(lua_State *L, lua_Debug *LDebug) { wxLuaInterpreter *luaInterpreter = wxFindLuaInterpreter(L); // during program shutdown this can be called - ignore it if (luaInterpreter == NULL) return; // FIXME - for select event types we don't want to do anything wxEventType evtType = luaInterpreter->GetStateVariables()->m_inEventType; if ((evtType != -1)) //(evtType == wxEVT_IDLE) && (evtType == wxEVT_PAINT) && //(evtType == wxEVT_DESTROY) && (evtType == wxEVT_CLOSE_WINDOW)) return; // they want to break the program, restore old debug hook, then error out if (luaInterpreter->GetBreak()) { // restore hook to previous state see wxLuaInterpreter::Break() luaInterpreter->SetLuaDebugHook(luaInterpreter->GetLuaDebugHookCount(), luaInterpreter->GetLuaDebugHookYield(), luaInterpreter->GetLuaDebugHookSendEvt(), luaInterpreter->GetLuaDebugHook()); terror(L, wx2lua(luaInterpreter->GetBreakMessage())); return; } if (luaInterpreter->GetLuaDebugHookSendEvt()) { int ret = 0; ret = lua_getinfo(L, "l", LDebug); // line (ldebug.currentline) wxLuaEvent event(wxEVT_LUA_DEBUG_HOOK, luaInterpreter->GetId(), luaInterpreter); event.m_lua_Debug = LDebug; event.SetInt(LDebug->currentline); luaInterpreter->SendEvent( event ); if (event.m_stop_interpreter) terror(L, "Interpreter stopped"); } // Try to yield *after* sending event to allow C++ gui update if (luaInterpreter->GetLuaDebugHookYield() > 0) { // yield based on number of ms passed NOT every hook event unsigned long last_time = luaInterpreter->GetLastLuaDebugHookTime(); unsigned long cur_time = wxGetLocalTimeMillis().GetLo(); if ((cur_time > last_time + luaInterpreter->GetLuaDebugHookYield()) || (cur_time < last_time)) // wrapped { luaInterpreter->SetLastLuaDebugHookTime( cur_time ); bool painting = false; #if WXWIN_COMPATIBILITY_24 || !wxCHECK_VERSION(2, 5, 0) wxNode* node; #else wxHashTable::Node* node; #endif // FIXME - wxGTK crashes if wxYield[IfNeeded] is called within a paint handler? I think luaInterpreter->GetStateVariables()->m_pTrackedList->BeginFind(); node = luaInterpreter->GetStateVariables()->m_pTrackedList->Next(); while (node) { if (wxDynamicCast(node->GetData(), wxPaintDC)) { painting = true; break; } node = luaInterpreter->GetStateVariables()->m_pTrackedList->Next(); } if (!painting) wxYieldIfNeeded(); } } } //----------------------------------------------------------------------------- // wxLuaEvent //----------------------------------------------------------------------------- DEFINE_LOCAL_EVENT_TYPE(wxEVT_LUA_CREATION) DEFINE_LOCAL_EVENT_TYPE(wxEVT_LUA_CONSOLE) DEFINE_LOCAL_EVENT_TYPE(wxEVT_LUA_WARNING) DEFINE_LOCAL_EVENT_TYPE(wxEVT_LUA_ERROR) DEFINE_LOCAL_EVENT_TYPE(wxEVT_LUA_DEBUG_HOOK) DEFINE_LOCAL_EVENT_TYPE(wxEVT_LUA_INIT) DEFINE_LOCAL_EVENT_TYPE(wxEVT_LUA_DEBUGGERATTACHED) DEFINE_LOCAL_EVENT_TYPE(wxEVT_LUA_SHUTDOWN) wxLuaEvent::wxLuaEvent(wxEventType commandType, int id, wxLuaInterpreter *interpreter) : wxNotifyEvent(commandType, id) { m_luaInterpreter = interpreter; m_lua_Debug = NULL; m_stop_interpreter = FALSE; } //----------------------------------------------------------------------------- // wxLuaInterpreter //----------------------------------------------------------------------------- IMPLEMENT_ABSTRACT_CLASS(wxLuaInterpreter, wxObject) wxLuaInterpreter::wxLuaInterpreter() : wxObject() { Init(); } wxLuaInterpreter::wxLuaInterpreter(wxEvtHandler *handler, int id) : wxObject() { Init(); Create(handler, id); } void wxLuaInterpreter::Init() { #ifdef WXLUA_THREAD_INTERCEPTION setupthreadhandlers(); #endif //WXLUA_THREAD_INTERCEPTION m_is_running = FALSE; m_user_break = FALSE; m_last_debug_hook_time = wxGetLocalTimeMillis().GetLo(); m_id = wxID_ANY; m_evtHandler = NULL; m_lua_State = NULL; m_luaAllocated = false; m_luaStateVariables = NULL; m_lua_debug_hook_count = 100; m_lua_debug_hook_yield = 50; m_lua_debug_hook_send_evt = FALSE; m_lua_debug_hook = 0; } bool wxLuaInterpreter::Create(lua_State *inL, wxEvtHandler *handler, int id) { if (Ok() && !Destroy(true)) return false; m_luaStateVariables = new wxLuaStateVariables; m_evtHandler = handler; m_id = id; // create a lua instance if (inL != NULL) { m_lua_State = inL; m_luaAllocated = false; } else { m_lua_State = lua_open(); m_luaAllocated = true; } lua_State *L = m_lua_State; // load some useful libraries luaopen_base(L); luaopen_table(L); luaopen_string(L); luaopen_math(L); luaopen_debug(L); luaopen_io(L); luaopen_loadlib(L); s_wxHashMapLuaInterpreter[L] = this; // Stick us into the lua interpreter - push key, value lua_pushstring( L, "__wxLuaInterpreter" ); lua_pushlightuserdata( L, (void*)this ); // set the value lua_settable( L, LUA_REGISTRYINDEX ); // register handlers to send events if (m_luaAllocated) { RegisterFunction(LuaPrint, wxT("print")); RegisterFunction(LuaAlert, wxT("_ALERT")); RegisterFunction(LuaTraceback, wxT("_TRACEBACK")); } // alert people that we've been created so they can finish setting us up wxLuaEvent event(wxEVT_LUA_CREATION, GetId(), this); SendEvent( event ); // now register bindings m_luaStateVariables->RegisterBindings(m_lua_State, true); return true; } wxLuaInterpreter::~wxLuaInterpreter() { if (Ok()) { m_evtHandler = NULL; // no events here, the handler may already be gone Destroy(true); } delete m_luaStateVariables; } void wxLuaInterpreter::GarbageCollectWindows(bool closeWindows) { // remove deleted windows if (Ok() && m_luaStateVariables->m_pWindowList && m_luaStateVariables->m_pWindowList->GetCount()) wxLuaCleanupWindows(m_luaStateVariables->m_pWindowList, !closeWindows); } bool wxLuaInterpreter::Destroy(bool force) { wxCHECK_MSG(Ok(), FALSE, wxT("Interpreter not created")); wxCHECK_MSG(!m_is_running, FALSE, wxT("Interpreter still running, can't destroy")); // remove deleted windows first if (m_luaStateVariables->m_pWindowList && m_luaStateVariables->m_pWindowList->GetCount()) wxLuaCleanupWindows(m_luaStateVariables->m_pWindowList, TRUE); // are there still windows? ask to abort deleting them if !force if (m_luaStateVariables->m_pWindowList && m_luaStateVariables->m_pWindowList->GetCount()) { int ret = wxOK; if (!force) { ret = wxMessageBox(wxT("Windows are still open, would you like to delete them?"), wxT("Delete existing windows?"), wxOK|wxCANCEL|wxICON_QUESTION); } if (ret == wxCANCEL) return FALSE; //wxPrintf(wxT("Deleting windows\n")); // delete windows and their eventhandler since they delete the LuaCallbacks // which require a lua_State wxLuaCleanupWindows(m_luaStateVariables->m_pWindowList, FALSE); // wait for wxWindow::Destroy() to really delete the windows //wxYieldIfNeeded(); } CleanupWxLua(m_lua_State, m_luaAllocated); s_wxHashMapLuaInterpreter.erase(m_lua_State); delete m_luaStateVariables; m_luaStateVariables = NULL; m_lua_State = NULL; m_evtHandler = NULL; return TRUE; } bool wxLuaInterpreter::Ok() const { return m_lua_State != NULL; } void wxLuaInterpreter::SetEventHandler(wxEvtHandler *evtHandler) { m_evtHandler = evtHandler; } int wxLuaInterpreter::RunFile(const wxString &filename) { wxCHECK_MSG(Ok(), -1, wxT("lua interpreter not created")); wxCHECK_MSG(!m_is_running, -1, wxT("lua interpreter is already running")); m_user_break = FALSE; m_is_running = TRUE; // int ret_val = lua_dofile(m_lua_State, wx2lua(filename)); int ret_val = LuaDoFile(m_lua_State, filename); // FIXME use LuaDoFile in RunFile ? m_is_running = FALSE; if (!m_user_break) (void)CheckRunError(ret_val); m_user_break = FALSE; return ret_val; } int wxLuaInterpreter::RunString(const wxString &script, const wxString& WXUNUSED(name)) { wxCHECK_MSG(Ok(), -1, wxT("lua interpreter not created")); wxCHECK_MSG(!m_is_running, -1, wxT("lua interpreter is already running")); m_user_break = FALSE; m_is_running = TRUE; //int ret_val = luaL_loadbuffer(m_lua_State, wx2lua(script), script.Len(), wx2lua(name)); int ret_val = lua_dostring(m_lua_State, wx2lua(script)); m_is_running = FALSE; // if it's been stopped then don't send this error message, already sent stopped one if (!m_user_break) (void)CheckRunError(ret_val); m_user_break = FALSE; return ret_val; } int wxLuaInterpreter::RunBuffer(const unsigned char buf[], size_t size, const wxString &name) { wxCHECK_MSG(Ok(), -1, wxT("lua interpreter not created")); wxCHECK_MSG(!m_is_running, -1, wxT("lua interpreter is already running")); m_user_break = FALSE; m_is_running = TRUE; //int ret_val = luaL_loadbuffer(m_lua_State, (const char*)buf, size, wx2lua(name)); int ret_val = lua_dobuffer(m_lua_State, (const char*)buf, size, wx2lua(name)); m_is_running = FALSE; if (!m_user_break) (void)CheckRunError(ret_val); m_user_break = FALSE; return ret_val; } void wxLuaInterpreter::Break(const wxString &msg) { wxCHECK_RET(Ok(), wxT("lua interpreter not created")); wxCHECK_RET(m_is_running, wxT("lua interpreter not running")); // Lua likes to be stopped within the debug hook, you get funny wxYield // recursion asserts if you call terror() within another wxYield, ie. from a gui button m_break_msg = msg; m_user_break = TRUE; SetLuaDebugHook(1, -1, FALSE); m_is_running = FALSE; } void wxLuaInterpreter::SetLuaDebugHook(int count, int yield, bool send_debug_evt, int hook) { wxCHECK_RET(Ok(), wxT("lua interpreter not created")); m_lua_debug_hook_count = count; m_lua_debug_hook_yield = yield; m_lua_debug_hook_send_evt = send_debug_evt; m_lua_debug_hook = hook; if (count > 0) { // These are the various hooks you can install //LUA_MASKCALL, LUA_MASKRET, LUA_MASKLINE, and LUA_MASKCOUNT //lua_sethook(m_lua_State, LuaDebugHook, LUA_MASKCALL | LUA_MASKLINE | LUA_MASKRET, 0); lua_sethook(m_lua_State, LuaDebugHook, hook, count); } else lua_sethook(m_lua_State, LuaDebugHook, 0, 0); // disable hook } unsigned long wxLuaInterpreter::GetLastLuaDebugHookTime() const { return m_last_debug_hook_time; } void wxLuaInterpreter::SetLastLuaDebugHookTime(unsigned long t) { m_last_debug_hook_time = t; } lua_State *wxLuaInterpreter::GetLuaState() const { return m_lua_State; } wxLuaStateVariables *wxLuaInterpreter::GetStateVariables() const { return m_luaStateVariables; } void wxLuaInterpreter::RegisterFunction(lua_CFunction func, const wxString &funcName) { wxCHECK_RET(Ok(), wxT("lua interpreter not created")); lua_register( GetLuaState(), wx2lua(funcName), func ); } void wxLuaInterpreter::DisplayError( const wxString &errorMsg ) { wxLuaEvent event(wxEVT_LUA_ERROR, GetId(), this); event.SetString(errorMsg); SendEvent( event ); } bool wxLuaInterpreter::CheckRunError(int rc) { wxString msg; if (!wxLuaCheckRunError(rc, &msg)) { wxLuaEvent event(wxEVT_LUA_ERROR, GetId(), this); event.SetString(msg); event.SetInt(-1); // don't know what line the error occured SendEvent( event ); return FALSE; } return TRUE; } void wxLuaInterpreter::SendEvent( wxLuaEvent &event ) const { if (GetEventHandler()) { event.SetEventObject( (wxObject*)this ); GetEventHandler()->ProcessEvent(event); } } --- NEW FILE: wxlcallb.cpp --- ///////////////////////////////////////////////////////////////////////////// // Name: wxLuaCall // Purpose: A simple class for a C++ wxWidgets program to embed wxLua // Author: Francis Irving // Created: 11/05/2002 // Copyright: (c) 2002 Creature Labs. All rights reserved. // Licence: wxWidgets licence ///////////////////////////////////////////////////////////////////////////// #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "wxlcallb.h" #endif // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif // WX_PRECOMP #include "wxlua/include/internal.h" #include "wxlua/include/wxlcallb.h" extern int s_wxEvent; //----------------------------------------------------------------------------- // wxLuaCallback //----------------------------------------------------------------------------- IMPLEMENT_CLASS(wxLuaCallback, wxEvtHandler); // Encapsulate a lua function reference for use by a event callback wxLuaCallback::wxLuaCallback( lua_State *L, int theRoutine, int id, wxEventType eventType, wxEvtHandler *pEvtHandler ) : m_luaState(L), m_luaStateVars(NULL), m_pHandler(pEvtHandler), m_id(id), m_eventType(eventType) { GET_LUASTATEVARS_RET(L) m_luaStateVars = stateVars; m_routine = tinsert(L, theRoutine); pEvtHandler->Connect( id, eventType, (wxObjectEventFunction)&wxLuaCallback::EventHandler, this); // FIXME - Need to track events attached to an application object // labenski - track all of them? useful to run ClearState when window is destroyed //if (pEvtHandler->IsKindOf(CLASSINFO(wxApp))) { m_luaStateVars->m_pAppHandlerList->Append(this); } } wxLuaCallback::~wxLuaCallback() { // Remove the reference to the Lua function that we are going to call if (m_luaState) tremove(m_luaState, m_routine); // delete the reference to this handler if (m_luaStateVars) m_luaStateVars->m_pAppHandlerList->DeleteObject(this); } // This function is called with "this" being of the type which the event is arriving // at. The user data is used to route it to the correct place. void wxLuaCallback::EventHandler(wxEvent& event) { wxLuaCallback *theCallback = (wxLuaCallback *) event.m_callbackUserData; if (!theCallback || !theCallback->GetLuaState() || !theCallback->m_luaStateVars) return; theCallback->m_luaStateVars->m_inEventType = event.GetEventType(); if (event.GetEventType() == wxEVT_DESTROY) { event.Skip(); theCallback->m_luaStateVars->m_pWindowList->DeleteObject((wxWindow*)event.GetEventObject()); // Disconnect all callbacks associated with this window's evthandler theCallback->ClearState(); wxEvtHandler *evtHandler = ((wxWindow*)event.GetEventObject())->GetEventHandler(); wxNode* node = theCallback->m_luaStateVars->m_pAppHandlerList->GetFirst(); while (node) { wxLuaCallback *pCallback = (wxLuaCallback *) node->GetData(); if ((pCallback != NULL) && (pCallback->GetEvtHandler() == evtHandler)) { pCallback->ClearState(); } node = node->GetNext(); } } else //if (theCallback->m_luaState) theCallback->CallFunction(&event); theCallback->m_luaStateVars->m_inEventType = -1; } // Call a lua function to handle an event. The lua function will receive // a single parameter, the type of event. void wxLuaCallback::CallFunction(wxEvent *pEvent) { // Cannot call it if Lua is gone or the interpreter has been destroyed // This can happen when the program exists since windows may be destroyed // after lua has been deleted if (!m_luaState || !wxFindLuaStateVariables(m_luaState)) return; int eventClassTag = s_wxEvent; GET_LUASTATEVARS_RET(m_luaState) const WXLUAEVENT *pLuaEvent = stateVars->GetLuaEvent(pEvent); if (pLuaEvent) eventClassTag = *pLuaEvent->eventClassTag; lua_checkstack(m_luaState,LUA_MINSTACK); int oldTop = lua_gettop(m_luaState); if (tget(m_luaState, m_routine)) { lua_pushvalue(m_luaState, LUA_GLOBALSINDEX); if (lua_setfenv(m_luaState, -2) != 0) { tpushusertag(m_luaState, pEvent, eventClassTag); LuaCall(m_luaState, 1, true); } else terror(m_luaState, "wxLua: CallFunction: function is not a Lua function."); } else terror(m_luaState, "wxLua: CallFunction: function has been garbage collected."); lua_settop(m_luaState, oldTop); } // ---------------------------------------------------------------------------- // wxLuaDestroyCallback // ---------------------------------------------------------------------------- IMPLEMENT_CLASS(wxLuaDestroyCallback, wxEvtHandler); wxLuaDestroyCallback::wxLuaDestroyCallback(lua_State *L, int id, wxEvtHandler *pHandler, int iTag) : m_luaState(L), m_luaStateVars(NULL), m_pHandler(pHandler), m_id(id) { GET_LUASTATEVARS_RET(L) m_luaStateVars = stateVars; // allocate a LUA proxy for the object const void **ptr = (const void **) lua_newuserdata(L, sizeof(void *)); if (ptr != NULL) { // save the address of the object in the proxy *ptr = pHandler; // and set the metatable of the proxy if (iTag != TLUA_NOTAG && tget(L, iTag)) { if (lua_setmetatable(L, -2) == 0) { terror(L, "wxLua: Unable to set metatable"); } } // get a reference to the destroy handler table if (tget(L, stateVars->m_wxDeleteTable)) { // create a reference to object lua_pushlightuserdata(L, pHandler); // key lua_pushvalue(L, -3); // value // save it in the destroy handler table lua_rawset(L, -3); lua_pop(L, 1); } stateVars->m_pDestroyHandlerList->Append(this); // connect the event handler pHandler->Connect(id, wxEVT_DESTROY, (wxObjectEventFunction)&wxLuaDestroyCallback::EventHandler, this); } else { terror(L, "wxLua: Out of memory"); } } wxLuaDestroyCallback::~wxLuaDestroyCallback() { if (m_luaStateVars) m_luaStateVars->m_pDestroyHandlerList->DeleteObject(this); } void wxLuaDestroyCallback::EventHandler(wxWindowDestroyEvent& event) { wxLuaDestroyCallback *theCallback = (wxLuaDestroyCallback *) event.m_callbackUserData; if (theCallback && (((wxWindow*)event.GetEventObject())->GetEventHandler() == m_pHandler)) { theCallback->OnDestroy(); } event.Skip(); } void wxLuaDestroyCallback::OnDestroy() { // FIXME - Is it an error to receive an event after you've deleted lua? // probably not if lua is getting shutdown if (!m_luaState || !m_luaStateVars) return; // Note: do not remove from m_pDestroyHandlerList here, wait 'till destructor if (tget(m_luaState, m_luaStateVars->m_wxDeleteTable)) { // clear the metatable reference in the lua proxy. lua_pushlightuserdata(m_luaState, m_pHandler); lua_rawget(m_luaState, -2); lua_pushnil(m_luaState); lua_setmetatable(m_luaState, -2); lua_pop(m_luaState, 2); } } --- NEW FILE: wxlhandl.cpp --- ///////////////////////////////////////////////////////////////////////////// // Purpose: Implements wxLuaApp and the wxGetBaseApp function // Author: J Winwood // Created: 14/11/2001 // Modifications: Thanks to Francis Irving for separating out into // Library and Standalone modules. // Copyright: (c) 2002 Creature Labs. All rights reserved. // Copyright: (c) 2001-2002 Lomtick Software. All rights reserved. // Licence: wxWidgets licence ///////////////////////////////////////////////////////////////////////////// #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "wxlhandl.h" #endif #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "wxlua/include/wxlhandl.h" #include "wxlua/include/internal.h" // ---------------------------------------------------------------------------- // wxLuaHandler - Allow for Custom Lua Handler (an alternative to wxLuaApp) // ---------------------------------------------------------------------------- wxLuaHandler* wxLuaHandler::sm_luahandler = NULL; wxLuaHandler::wxLuaHandler() { wxASSERT(!sm_luahandler); sm_luahandler = this; } wxLuaHandler::~wxLuaHandler() { sm_luahandler = NULL; } wxLuaHandler& wxGetLuaHandler() { return *wxLuaHandler::sm_luahandler; } |