1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
6 // Copyright (C) 2013-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "nel/gui/lua_helper.h"
24 #include "nel/misc/file.h"
26 #ifdef LUA_NEVRAX_VERSION
27 #include "lua_ide_dll_nevrax/include/lua_ide_dll/ide_interface.h" // external debugger
31 #include "nel/gui/lua_loadlib.h"
33 // to get rid of you_must_not_use_assert___use_nl_assert___read_debug_h_file messages
40 #define assert(x) nlassert(x)
45 // Always use unique_ptr with ValyriaTear/luabind on Ubuntu 20,
46 // since the setting is not stored in build_information.hpp
47 #ifndef LUABIND_USE_CXX11
48 #define LUABIND_USE_CXX11
51 #include <luabind/luabind.hpp>
52 #include <nel/misc/algo.h>
53 #include <nel/misc/path.h>
60 using namespace NLMISC
;
69 namespace LuaHelperStuff
71 void formatLuaStackContext( std::string
&stackContext
)
73 stackContext
= std::string( "@{FC8A}" ).append( stackContext
).append( "@{FC8F} " );
76 std::string
formatLuaErrorSysInfo( const std::string
&error
)
78 return std::string( "@{FC8F}" ).append( error
);
81 std::string
formatLuaErrorNlWarn( const std::string
&error
)
83 // Remove color tags (see formatLuaErrorSC())
84 std::string ret
= error
;
85 strFindReplace( ret
, "@{FC8A}", "" );
86 strFindReplace( ret
, "@{FC8F}", "" );
91 // ***************************************************************************
92 const char *CLuaState::_NELSmallScriptTableName
= "NELSmallScriptTable";
93 uint
CLuaStackChecker::_ExceptionContextCounter
= 0;
95 // ***************************************************************************
96 void CLuaStackChecker::incrementExceptionContextCounter()
98 //H_AUTO(Lua_CLuaStackChecker_incrementExceptionContextCounter)
99 ++ _ExceptionContextCounter
;
102 // ***************************************************************************
103 void CLuaStackChecker::decrementExceptionContextCounter()
105 //H_AUTO(Lua_CLuaStackChecker_decrementExceptionContextCounter)
106 nlassert(_ExceptionContextCounter
> 0);
107 -- _ExceptionContextCounter
;
111 #ifdef LUA_NEVRAX_VERSION
112 ILuaIDEInterface
*LuaDebuggerIDE
= NULL
;
113 static bool LuaDebuggerVisible
= false;
117 HMODULE LuaDebuggerModule
= 0;
120 void luaDebuggerMainLoop()
122 #ifdef LUA_NEVRAX_VERSION
123 if (!LuaDebuggerIDE
) return;
124 if (!LuaDebuggerVisible
)
126 LuaDebuggerIDE
->showDebugger(true);
127 LuaDebuggerIDE
->expandProjectTree();
128 LuaDebuggerIDE
->sortFiles();
129 LuaDebuggerVisible
= true;
131 LuaDebuggerIDE
->doMainLoop();
137 static std::allocator
<uint8
> l_stlAlloc
;
140 static void l_free_func(void *block
, int oldSize
)
142 l_stlAlloc
.deallocate((uint8
*) block
, oldSize
);
145 static void *l_realloc_func(void *b
, int os
, int s
)
147 if (os
== s
) return b
;
148 void *newB
= l_stlAlloc
.allocate(s
);
149 memcpy(newB
, b
, std::min(os
, s
));
156 const int MinGCThreshold
= 128; // min value at which garbage collector will be triggered (in kilobytes)
157 // ***************************************************************************
158 CLuaState::CLuaState( bool debugger
)
162 #ifdef LUA_NEVRAX_VERSION
163 _GCThreshold
= MinGCThreshold
;
169 #ifndef LUA_NEVRAX_VERSION
170 static bool warningShown
= false;
173 nldebug( "Lua debugger was asked, but the static lua library against which the client was linked is too old. Please update to lua-5.0.2_nevrax. Debugging won't be available!" );
174 //MessageBox (NULL, "Lua debugger was asked, but the static lua library against which the client was linked is too old. Please update to lua-5.0.2_nevrax. Debugging won't be available!", "Lua support", MB_OK);
178 nlassert(LuaDebuggerIDE
== NULL
); // for now, only one debugger supported...
180 LuaDebuggerModule
= ::LoadLibrary("lua_ide2_dll_d.dll");
182 LuaDebuggerModule
= ::LoadLibrary("lua_ide2_dll_r.dll");
184 if (LuaDebuggerModule
)
186 TGetLuaIDEInterfaceVersion getVersion
= (TGetLuaIDEInterfaceVersion
) GetProcAddress(LuaDebuggerModule
, "GetLuaIDEInterfaceVersion");
187 nlassert(getVersion
);
188 int dllInterfaceVersion
= getVersion();
189 if (dllInterfaceVersion
> LUA_IDE_INTERFACE_VERSION
)
191 MessageBox (NULL
, "Lua debugger interface is newer than the application. Debugging will be disabled. Please update your client", "Lua support", MB_OK
);
193 else if (dllInterfaceVersion
< LUA_IDE_INTERFACE_VERSION
)
195 MessageBox (NULL
, "Lua debugger interface is too old. Lua debugging will be disabled. Please ask for a more recent dll.", "Lua support", MB_OK
);
199 TGetLuaIDEInterface getter
= (TGetLuaIDEInterface
) GetProcAddress(LuaDebuggerModule
, "GetLuaIDEInterface");
201 LuaDebuggerIDE
= getter();
202 LuaDebuggerIDE
->prepareDebug("save\\___external_debug.lpr", l_realloc_func
, l_free_func
, Driver
->getDisplay());
203 _State
= LuaDebuggerIDE
->getLuaState();
212 #ifdef LUA_NEVRAX_VERSION
213 _State
= lua_open(l_realloc_func
, l_free_func
);
214 #elif defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501
215 _State
= luaL_newstate();
222 // *** Load base libs
224 CLuaStackChecker
lsc(this);
225 #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501
226 luaL_openlibs(_State
);
228 luaopen_base (_State
);
229 luaopen_table (_State
);
231 luaopen_string (_State
);
232 luaopen_math (_State
);
233 luaopen_debug (_State
);
237 // Lua socket library for MobDebug, optional
238 if (NLMISC::CFile::fileExists("socket\\core.dll"))
240 // Load socket\core.dll dynamically
241 m_LuaSocket
= LoadLibraryW(L
"socket\\core.dll");
244 nlwarning("Lua socket library found, but failed to load");
248 void *luaopen_socket_core
= (void *)GetProcAddress(m_LuaSocket
, "luaopen_socket_core");
249 if (!luaopen_socket_core
)
251 nlwarning("Lua socket library loaded, but `luaopen_socket_core` not found");
252 FreeLibrary(m_LuaSocket
);
257 // preload['socket.core'] = luaopen_socket_core
258 #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501
259 lua_getglobal(_State
, "package");
260 lua_getfield(_State
, -1, "preload");
261 lua_pushcfunction(_State
, (lua_CFunction
)luaopen_socket_core
);
262 lua_setfield(_State
, -2, "socket.core");
264 nlinfo("Lua socket library preloaded");
275 // open are buggy????
279 // *** Register basics
280 CLuaStackChecker
lsc(this);
282 // do: LUA_REGISTRYINDEX.(lightuserdata*)this.classes= {}
283 pushLightUserData((void *) this);
286 newTable(); // registry class
288 setTable(LUA_REGISTRYINDEX
);
290 // add pointer from lua state to this CLuaState object
291 // do: LUA_REGISTRYINDEX.(lightuserdata*)_State= this
292 pushLightUserData((void *) _State
); // NB : as creator of the state, we make the assumption that
293 // no one will be using this pointer in the registry (cf. ref manual about registry)
294 pushLightUserData((void *) this);
295 setTable(LUA_REGISTRYINDEX
);
297 // Create the Table that contains Function cache for small script execution
298 push(_NELSmallScriptTableName
); // 1:TableName
299 newTable(); // 1:TableName 2:table
300 setTable(LUA_REGISTRYINDEX
); // ...
304 luabind::open(_State
);
308 // ***************************************************************************
309 CLuaStackRestorer::CLuaStackRestorer(CLuaState
*state
, int finalSize
) : _FinalSize(finalSize
), _State(state
)
313 // ***************************************************************************
314 CLuaStackRestorer::~CLuaStackRestorer()
317 _State
->setTop(_FinalSize
);
321 static int NoOpReportHook( int /* reportType */, char * /* message */, int * /* returnValue */ )
328 // ***************************************************************************
329 CLuaState::~CLuaState()
333 #ifdef LUA_NEVRAX_VERSION
343 #ifdef LUA_NEVRAX_VERSION
344 LuaDebuggerIDE
->stopDebug(); // this will also close the lua state
345 LuaDebuggerIDE
= NULL
;
346 LuaDebuggerVisible
= false;
348 nlassert(LuaDebuggerModule
)
349 _CrtSetReportHook(NoOpReportHook
); // prevent dump of memory leaks at this point
350 //::FreeLibrary(LuaDebuggerModule); // don't free the library now (seems that it destroy, the main window, causing
351 // a crash when the app window is destroyed for real...
352 // -> FreeLibrary will be called when the application is closed
353 LuaDebuggerModule
= 0;
358 // Clear Small Script Cache
360 _SmallScriptCache
.clear();
365 FreeLibrary(m_LuaSocket
);
371 // ***************************************************************************
372 CLuaState
*CLuaState::fromStatePointer(lua_State
*state
)
374 //H_AUTO(Lua_CLuaState_fromStatePointer)
376 int initialStackSize
= lua_gettop(state
);
377 lua_checkstack(state
, initialStackSize
+ 2);
378 lua_pushlightuserdata(state
, (void *) state
);
379 lua_gettable(state
, LUA_REGISTRYINDEX
);
380 if (!lua_islightuserdata(state
, -1))
385 CLuaState
*ls
= (CLuaState
*) lua_touserdata(state
, -1);
387 nlassert(initialStackSize
== lua_gettop(state
));
391 // ***************************************************************************
394 const std::string
*Str
;
401 void CLuaState::loadScript(const std::string
&code
, const std::string
&dbgSrc
)
403 //H_AUTO(Lua_CLuaState_loadScript)
404 if (code
.empty()) return;
407 static const char *luaChunkReaderFromString(lua_State
* /* L */, void *ud
, size_t *sz
)
409 CLuaReader
*rd
= (CLuaReader
*) ud
;
413 *sz
= rd
->Str
->size();
414 return rd
->Str
->c_str();
427 int result
= lua_load(_State
, CHelper::luaChunkReaderFromString
, (void *) &rd
, dbgSrc
.c_str()
428 #if LUA_VERSION_NUM >= 502
434 // pop the error code
435 string err
= toString();
438 throw ELuaParseError(err
);
442 // ***************************************************************************
443 void CLuaState::executeScriptInternal(const std::string
&code
, const std::string
&dbgSrc
, int numRet
)
445 //H_AUTO(Lua_CLuaState_executeScriptInternal)
446 CLuaStackChecker
lsc(this, numRet
);
449 loadScript(code
, dbgSrc
);
452 if (pcall(0, numRet
) != 0)
454 // pop the error code
455 string err
= toString();
458 throw ELuaExecuteError(err
);
462 // ***************************************************************************
463 void CLuaState::executeScript(const std::string
&code
, int numRet
)
465 //H_AUTO(Lua_CLuaState_executeScript)
466 // run the script, with dbgSrc==script
467 executeScriptInternal(code
, code
, numRet
);
470 // ***************************************************************************
471 bool CLuaState::executeScriptNoThrow(const std::string
&code
, int numRet
)
473 //H_AUTO(Lua_CLuaState_executeScriptNoThrow)
476 executeScript(code
, numRet
);
478 catch (const ELuaError
&e
)
486 // ***************************************************************************
487 bool CLuaState::executeFile(const std::string
&pathName
)
489 //H_AUTO(Lua_CLuaState_executeFile)
492 if(!inputFile
.open(pathName
))
495 #ifdef LUA_NEVRAX_VERSION
498 std::string path
= NLMISC::CPath::getCurrentPath() + "/" + pathName
.c_str();
499 path
= CPath::standardizeDosPath(path
);
500 LuaDebuggerIDE
->addFile(path
.c_str());
504 // load the script text
507 while(!inputFile.eof())
510 inputFile.getline(tmpBuff, 5000);
515 script
.resize(CFile::getFileSize(pathName
));
516 inputFile
.serialBuffer((uint8
*) &script
[0], (uint
)script
.size());
519 // execute the script text, with dbgSrc==filename (use @ for lua internal purpose)
521 // Paths need to be correct for debugging to work
522 std::string pathNameStandardized
= pathName
;
523 if (pathNameStandardized
.size() > 1)
525 if (pathNameStandardized
[1] == ':' && pathNameStandardized
[0] >= 'a' && pathNameStandardized
[0] <= 'z')
526 pathNameStandardized
[0] -= 'a' - 'A';
527 for (ptrdiff_t i
= 0; i
< (ptrdiff_t)pathNameStandardized
.size(); ++i
)
529 if (pathNameStandardized
[i
] == '/')
530 pathNameStandardized
[i
] = '\\';
534 const std::string
&pathNameStandardized
= pathName
;
536 executeScriptInternal(script
, string("@") + pathNameStandardized
);
541 // ***************************************************************************
542 void CLuaState::executeSmallScript(const std::string
&script
)
544 //H_AUTO(Lua_CLuaState_executeSmallScript)
545 if (script
.empty()) return;
546 // *** if the small script has not already been called before, parse it now
547 TSmallScriptCache::iterator it
= _SmallScriptCache
.find(script
);
548 if(it
==_SmallScriptCache
.end())
550 CLuaStackChecker
lsc(this);
552 // add it to a function
553 loadScript(script
, script
);
555 // Assign the method to the NEL table: NELSmallScriptTable[_SmallScriptPool]= function
556 push(_NELSmallScriptTableName
); // 1:function 2:NelTableName
557 getTable(LUA_REGISTRYINDEX
); // 1:function 2:NelTable
558 insert(-2); // 1:NelTable 2:function
559 rawSetI(-2, _SmallScriptPool
); // 1:NelTable
563 it
= _SmallScriptCache
.insert(make_pair(script
, _SmallScriptPool
)).first
;
569 // *** Execute the function associated to the script
570 CLuaStackChecker
lsc(this);
571 push(_NELSmallScriptTableName
); // 1:NelTableName
572 getTable(LUA_REGISTRYINDEX
); // 1:NelTable
573 // get the function at the given index in the "NELSmallScriptTable" table
574 rawGetI(-1, it
->second
); // 1:NelTable 2:function
577 if (pcall(0, 0) != 0)
579 // Stack: 1: NelTable 2:errorcode
580 // pop the error code, and clear stack
581 string err
= toString();
585 throw ELuaExecuteError(err
);
595 // ***************************************************************************
596 void CLuaState::registerFunc(const char *name
, lua_CFunction function
)
598 //H_AUTO(Lua_CLuaState_registerFunc)
599 lua_register(_State
, name
, function
);
602 // ***************************************************************************
603 void CLuaState::pushCClosure(lua_CFunction function
, int n
)
605 //H_AUTO(Lua_CLuaState_pushCClosure)
607 nlassert(getTop() >= n
);
608 lua_pushcclosure(_State
, function
, n
);
611 // ***************************************************************************
612 void CLuaState::push(TLuaWrappedFunction function
)
614 //H_AUTO(Lua_CLuaState_push)
617 static int callFunc(lua_State
*ls
)
620 TLuaWrappedFunction func
= (TLuaWrappedFunction
) lua_touserdata(ls
, lua_upvalueindex(1));
621 CLuaState
*state
= (CLuaState
*) lua_touserdata(ls
, lua_upvalueindex(2));
624 // get real function pointer from the values in the closure
626 int initialStackSize
= state
->getTop();
629 // call the actual function
630 numResults
= func(*state
);
632 catch(const std::exception
&e
)
634 // restore stack to its initial size
635 state
->setTop(initialStackSize
);
636 lua_pushstring(ls
, e
.what());
637 // TODO : see if this is safe to call lua error there" ... (it does a long jump)
643 pushLightUserData((void *) function
);
644 pushLightUserData((void *) this);
645 pushCClosure(CForwarder::callFunc
, 2);
648 // ***************************************************************************
650 void CLuaState::registerFunc(const char *name
, TLuaWrappedFunction function
)
652 //H_AUTO(Lua_CLuaState_registerFunc)
654 CLuaStackChecker
lsc(this);
655 #if LUA_VERSION_NUM >= 502
660 #if LUA_VERSION_NUM >= 502
661 setTable(-3); // -3 is the pushGlobalTable
662 pop(1); // pop the pushGlobalTable value (setTable popped the 2 pushes)
664 setTable(LUA_GLOBALSINDEX
);
669 // ***************************************************************************
670 bool CLuaState::getTableBooleanValue(const char *name
, bool defaultValue
)
672 //H_AUTO(Lua_CLuaState_getTableBooleanValue)
681 bool result
= toBoolean(-1);
686 // ***************************************************************************
687 double CLuaState::getTableNumberValue(const char *name
, double defaultValue
)
689 //H_AUTO(Lua_CLuaState_getTableNumberValue)
698 double result
= toNumber(-1);
703 // ***************************************************************************
704 sint64
CLuaState::getTableIntegerValue(const char *name
, sint64 defaultValue
)
706 //H_AUTO(Lua_CLuaState_getTableIntegerValue)
715 sint64 result
= toInteger(-1);
720 // ***************************************************************************
721 const char *CLuaState::getTableStringValue(const char *name
, const char *defaultValue
)
723 //H_AUTO(Lua_CLuaState_getTableStringValue)
732 const char *result
= toString(-1);
737 // ***************************************************************************
738 void CLuaState::getStackContext(string
&ret
, uint stackLevel
)
740 //H_AUTO(Lua_CLuaState_getStackContext)
744 if(lua_getstack (_State
, stackLevel
, &dbg
))
746 if(lua_getinfo(_State
, "lS", &dbg
))
748 ret
= NLMISC::toString("%s:%d:", dbg
.short_src
, dbg
.currentline
);
753 // ***************************************************************************
754 int CLuaState::pcallByNameGlobal(const char *functionName
, int nargs
, int nresults
, int errfunc
/*= 0*/)
756 int initialStackSize
= getTop();
757 nlassert(functionName
);
758 #if LUA_VERSION_NUM >= 502
761 nlassert(isTable(LUA_GLOBALSINDEX
));
762 pushValue(LUA_GLOBALSINDEX
);
764 return pcallByNameInternal(functionName
, nargs
, nresults
, errfunc
, initialStackSize
);
767 int CLuaState::pcallByName(const char *functionName
, int nargs
, int nresults
, int funcTableIndex
, int errfunc
/*= 0*/)
769 int initialStackSize
= getTop();
770 nlassert(functionName
);
771 nlassert(isTable(funcTableIndex
));
772 pushValue(funcTableIndex
);
773 return pcallByNameInternal(functionName
, nargs
, nresults
, errfunc
, initialStackSize
);
776 int CLuaState::pcallByNameInternal(const char *functionName
, int nargs
, int nresults
, int errfunc
/*= 0*/, int initialStackSize
)
778 //H_AUTO(Lua_CLuaState_pcallByName)
781 remove(-2); // get rid of the table
782 nlassert(getTop() >= nargs
); // not enough arguments on the stack
783 // insert function before its arguments
785 int result
= pcall(nargs
, nresults
, errfunc
);
786 int currSize
= getTop();
789 nlassert(currSize
== initialStackSize
- nargs
+ nresults
);
793 // errors, the stack contains a single string
796 nlassert(currSize
== initialStackSize
- nargs
+ 1);
798 // else if there's an error handler, can't know the size of stack
803 // ***************************************************************************
804 void CLuaState::dumpStack()
806 //H_AUTO(Lua_CLuaState_dumpStack)
807 nlinfo("LUA STACK CONTENT (size = %d)", getTop());
808 nlinfo("=================");
809 CLuaStackChecker
lsc(this);
810 for(int k
= 1; k
<= getTop(); ++k
)
813 std::string value
= toString(-1) ? toString(-1) : "?";
814 nlinfo("Stack entry %d : type = %s, value = %s", k
, getTypename(type(-1)), value
.c_str());
819 // ***************************************************************************
820 void CLuaState::getStackAsString(std::string
&dest
)
822 //H_AUTO(Lua_CLuaState_getStackAsString)
823 dest
= NLMISC::toString("Stack size = %d\n", getTop());
824 CLuaStackChecker
lsc(this);
825 for(int k
= 1; k
<= getTop(); ++k
)
828 std::string value
= toString(-1) ? toString(-1) : "?";
829 dest
+= NLMISC::toString("Stack entry %d : type = %s, value = %s\n", k
, getTypename(type(-1)), value
.c_str());
834 //================================================================================
835 CLuaStackChecker::~CLuaStackChecker()
838 if (!_ExceptionContextCounter
)
840 int currSize
= _State
->getTop();
841 if (currSize
!= _FinalWantedSize
)
843 static volatile bool assertWanted
= true;
846 nlwarning("Lua stack size error : expected size is %d, current size is %d", _FinalWantedSize
, currSize
);
854 // this object dtor was called because an exception was thrown, so let the exception
855 // propagate (the stack must be broken, but because of the exception, not because of code error)
856 _State
->setTop(_FinalWantedSize
);
860 // ***************************************************************************
861 void ELuaWrappedFunctionException::init(CLuaState
*ls
, const std::string
&reason
)
863 //H_AUTO(Lua_ELuaWrappedFunctionException_init)
864 // Print first Lua Stack Context
867 ls
->getStackContext(_Reason
, 1); // 1 because 0 is the current C function => return 1 for script called
868 // enclose with cool colors
869 LuaHelperStuff::formatLuaStackContext(_Reason
);
876 // ***************************************************************************
877 ELuaWrappedFunctionException::ELuaWrappedFunctionException(CLuaState
*luaState
)
879 //H_AUTO(Lua_ELuaWrappedFunctionException_ELuaWrappedFunctionException)
883 // ***************************************************************************
884 ELuaWrappedFunctionException::ELuaWrappedFunctionException(CLuaState
*luaState
, const std::string
&reason
)
886 //H_AUTO(Lua_ELuaWrappedFunctionException_ELuaWrappedFunctionException)
887 init(luaState
, reason
);
890 // ***************************************************************************
891 ELuaWrappedFunctionException::ELuaWrappedFunctionException(CLuaState
*luaState
, const char *format
, ...)
893 //H_AUTO(Lua_ELuaWrappedFunctionException_ELuaWrappedFunctionException)
895 NLMISC_CONVERT_VARGS (reason
, format
, NLMISC::MaxCStringSize
);
896 init(luaState
, reason
);
899 //================================================================================
900 void CLuaState::newTable()
902 //H_AUTO(Lua_CLuaState_newTable)
903 nlverify( lua_checkstack(_State
, 1) );
904 lua_newtable(_State
);
907 //================================================================================
908 int CLuaState::getGCCount()
910 //H_AUTO(Lua_CLuaState_getGCCount)
911 #if LUA_VERSION_NUM >= 502
915 return lua_getgccount(_State
);
919 //================================================================================
920 int CLuaState::getGCThreshold()
922 //H_AUTO(Lua_CLuaState_getGCThreshold)
923 #ifdef LUA_NEVRAX_VERSION
926 # if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501
927 return lua_gc(_State
, LUA_GCCOUNT
, 0);
929 return lua_getgcthreshold(_State
);
934 //================================================================================
935 void CLuaState::setGCThreshold(int kb
)
937 //H_AUTO(Lua_CLuaState_setGCThreshold)
938 #ifdef LUA_NEVRAX_VERSION
942 # if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501
943 lua_gc(_State
, LUA_GCCOLLECT
, kb
);
945 lua_setgcthreshold(_State
, kb
);
950 //================================================================================
951 void CLuaState::handleGC()
953 //H_AUTO(Lua_CLuaState_handleGC)
954 #ifdef LUA_NEVRAX_VERSION
955 // must handle gc manually with the refcounted version
956 int gcCount
= getGCCount();
957 if (gcCount
>= _GCThreshold
)
959 nlwarning("Triggering GC : memory in use = %d kb, current threshold = %d kb", gcCount
, _GCThreshold
);
960 lua_setgcthreshold(_State
, 0);
961 gcCount
= getGCCount();
962 _GCThreshold
= std::max(MinGCThreshold
, gcCount
* 2);
963 nlwarning("After GC : memory in use = %d kb, threshold = %d kb", gcCount
, _GCThreshold
);