LuaState.cs 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843
  1. // The MIT License (MIT)
  2. // Copyright 2015 Siney/Pangweiwei siney@yeah.net
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //#define LUA_DEBUG
  22. namespace SLua
  23. {
  24. using System;
  25. using System.Collections.Generic;
  26. using System.Collections;
  27. using System.Text;
  28. #if LUA_DEBUG
  29. using System.Security.Cryptography;
  30. #endif
  31. #if !SLUA_STANDALONE
  32. using UnityEngine;
  33. #else
  34. using System.IO;
  35. #endif
  36. abstract public class LuaVar : IDisposable
  37. {
  38. protected LuaState state = null;
  39. protected int valueref = 0;
  40. public IntPtr L
  41. {
  42. get
  43. {
  44. return state.L;
  45. }
  46. }
  47. public int Ref
  48. {
  49. get
  50. {
  51. return valueref;
  52. }
  53. }
  54. public LuaVar()
  55. {
  56. state = null;
  57. }
  58. public LuaVar(LuaState l, int r)
  59. {
  60. state = l;
  61. valueref = r;
  62. }
  63. public LuaVar(IntPtr l, int r)
  64. {
  65. state = LuaState.get(l);
  66. valueref = r;
  67. }
  68. ~LuaVar()
  69. {
  70. Dispose(false);
  71. }
  72. public void Dispose()
  73. {
  74. Dispose(true);
  75. GC.SuppressFinalize(this);
  76. }
  77. static void unref(IntPtr l, int r)
  78. {
  79. LuaDLL.lua_unref(l, r);
  80. }
  81. public virtual void Dispose(bool disposeManagedResources)
  82. {
  83. if (valueref != 0)
  84. {
  85. state.gcRef(unref, valueref);
  86. valueref = 0;
  87. }
  88. }
  89. public void push(IntPtr l)
  90. {
  91. LuaDLL.lua_getref(l, valueref);
  92. }
  93. public override int GetHashCode()
  94. {
  95. return base.GetHashCode();
  96. }
  97. public override bool Equals(object obj)
  98. {
  99. if (obj is LuaVar)
  100. {
  101. return this == (LuaVar)obj;
  102. }
  103. return false;
  104. }
  105. public static bool operator ==(LuaVar x, LuaVar y)
  106. {
  107. if ((object)x == null || (object)y == null)
  108. return (object)x == (object)y;
  109. return Equals(x, y) == 1;
  110. }
  111. public static bool operator !=(LuaVar x, LuaVar y)
  112. {
  113. if ((object)x == null || (object)y == null)
  114. return (object)x != (object)y;
  115. return Equals(x, y) != 1;
  116. }
  117. static int Equals(LuaVar x, LuaVar y)
  118. {
  119. x.push(x.L);
  120. y.push(x.L);
  121. int ok = LuaDLL.lua_equal(x.L, -1, -2);
  122. LuaDLL.lua_pop(x.L, 2);
  123. return ok;
  124. }
  125. }
  126. public class LuaThread : LuaVar
  127. {
  128. public LuaThread(IntPtr l, int r)
  129. : base(l, r)
  130. { }
  131. }
  132. public class LuaDelegate : LuaFunction
  133. {
  134. public object d;
  135. public LuaDelegate(IntPtr l, int r)
  136. : base(l, r)
  137. {
  138. }
  139. static void unref(IntPtr l, int r)
  140. {
  141. LuaObject.removeDelgate(l, r);
  142. LuaDLL.lua_unref(l, r);
  143. }
  144. public override void Dispose(bool disposeManagedResources)
  145. {
  146. if (valueref != 0)
  147. {
  148. state.gcRef(unref, valueref);
  149. valueref = 0;
  150. }
  151. }
  152. }
  153. public class LuaFunction : LuaVar
  154. {
  155. public LuaFunction(LuaState l, int r)
  156. : base(l, r)
  157. {
  158. }
  159. public LuaFunction(IntPtr l, int r)
  160. : base(l, r)
  161. {
  162. }
  163. public bool pcall(int nArgs, int errfunc)
  164. {
  165. if (!state.isMainThread())
  166. {
  167. Logger.LogError("Can't call lua function in bg thread");
  168. return false;
  169. }
  170. LuaDLL.lua_getref(L, valueref);
  171. if (!LuaDLL.lua_isfunction(L, -1))
  172. {
  173. LuaDLL.lua_pop(L, 1);
  174. throw new Exception("Call invalid function.");
  175. }
  176. LuaDLL.lua_insert(L, -nArgs - 1);
  177. if (LuaDLL.lua_pcall(L, nArgs, -1, errfunc) != 0)
  178. {
  179. LuaDLL.lua_pop(L, 1);
  180. return false;
  181. }
  182. return true;
  183. }
  184. bool innerCall(int nArgs, int errfunc)
  185. {
  186. bool ret = pcall(nArgs, errfunc);
  187. LuaDLL.lua_remove(L, errfunc);
  188. return ret;
  189. }
  190. public object call()
  191. {
  192. int error = LuaObject.pushTry(state.L);
  193. if (innerCall(0, error))
  194. {
  195. return state.topObjects(error - 1);
  196. }
  197. return null;
  198. }
  199. public object call(params object[] args)
  200. {
  201. int error = LuaObject.pushTry(state.L);
  202. for (int n = 0; args != null && n < args.Length; n++)
  203. {
  204. LuaObject.pushVar(L, args[n]);
  205. }
  206. if (innerCall(args != null ? args.Length : 0, error))
  207. {
  208. return state.topObjects(error - 1);
  209. }
  210. return null;
  211. }
  212. public bool TryCall(out object ret, params object[] args)
  213. {
  214. int error = LuaObject.pushTry(state.L);
  215. for (int n = 0; args != null && n < args.Length; n++)
  216. {
  217. LuaObject.pushVar(L, args[n]);
  218. }
  219. if (innerCall(args != null ? args.Length : 0, error))
  220. {
  221. ret = state.topObjects(error - 1);
  222. return true;
  223. }
  224. ret = null;
  225. return false;
  226. }
  227. public object call(LuaTable self, params object[] args)
  228. {
  229. int error = LuaObject.pushTry(state.L);
  230. LuaObject.pushVar(L, self);
  231. for (int n = 0; args != null && n < args.Length; n++)
  232. {
  233. LuaObject.pushVar(L, args[n]);
  234. }
  235. if (innerCall((args != null ? args.Length : 0) + 1, error))
  236. {
  237. return state.topObjects(error - 1);
  238. }
  239. return null;
  240. }
  241. public T cast<T>() where T : class
  242. {
  243. return LuaObject.delegateCast(this, typeof(T)) as T;
  244. }
  245. }
  246. public class LuaTable : LuaVar, IEnumerable<LuaTable.TablePair>
  247. {
  248. public struct TablePair
  249. {
  250. public object key;
  251. public object value;
  252. }
  253. public LuaTable(IntPtr l, int r)
  254. : base(l, r)
  255. {
  256. }
  257. public LuaTable(LuaState l, int r)
  258. : base(l, r)
  259. {
  260. }
  261. public LuaTable(LuaState state)
  262. : base(state, 0)
  263. {
  264. LuaDLL.lua_newtable(L);
  265. valueref = LuaDLL.luaL_ref(L, LuaIndexes.LUA_REGISTRYINDEX);
  266. }
  267. // if wholekey is true, don't split key by '.'
  268. public object get(string key, bool wholekey = false, bool rawget = false)
  269. {
  270. return state.getObject(valueref, key, wholekey, rawget);
  271. }
  272. // if wholekey is true, don't split key by '.'
  273. public void set(string key, object v, bool wholekey = false, bool rawset = false)
  274. {
  275. state.setObject(valueref, key, v, wholekey, rawset);
  276. }
  277. public object this[string key]
  278. {
  279. get
  280. {
  281. return state.getObject(valueref, key);
  282. }
  283. set
  284. {
  285. state.setObject(valueref, key, value);
  286. }
  287. }
  288. public object this[int index]
  289. {
  290. get
  291. {
  292. return state.getObject(valueref, index);
  293. }
  294. set
  295. {
  296. state.setObject(valueref, index, value);
  297. }
  298. }
  299. public object invoke(string func, params object[] args)
  300. {
  301. using (LuaFunction f = (LuaFunction)this[func])
  302. {
  303. if (f != null)
  304. {
  305. return f.call(args);
  306. }
  307. }
  308. throw new Exception(string.Format("Can't find {0} function", func));
  309. }
  310. public int length()
  311. {
  312. int n = LuaDLL.lua_gettop(L);
  313. push(L);
  314. int l = LuaDLL.lua_rawlen(L, -1);
  315. LuaDLL.lua_settop(L, n);
  316. return l;
  317. }
  318. public bool IsEmpty
  319. {
  320. get
  321. {
  322. int top = LuaDLL.lua_gettop(L);
  323. LuaDLL.lua_getref(L, this.Ref);
  324. LuaDLL.lua_pushnil(L);
  325. bool ret = LuaDLL.lua_next(L, -2) > 0;
  326. LuaDLL.lua_settop(L, top);
  327. return !ret;
  328. }
  329. }
  330. public int GetInt(string key)
  331. {
  332. var rtn = this[key].ToString();
  333. int r = 0;
  334. int.TryParse(rtn, out r);
  335. return r;
  336. }
  337. public string GetString(string key)
  338. {
  339. return (this[key].ToString());
  340. }
  341. public class Enumerator : IEnumerator<TablePair>, IDisposable
  342. {
  343. LuaTable t;
  344. int indext = -1;
  345. TablePair current = new TablePair();
  346. int iterPhase = 0;
  347. public Enumerator(LuaTable table)
  348. {
  349. t = table;
  350. Reset();
  351. }
  352. public bool MoveNext()
  353. {
  354. if (indext < 0)
  355. return false;
  356. if (iterPhase == 0)
  357. {
  358. LuaDLL.lua_pushnil(t.L);
  359. iterPhase = 1;
  360. }
  361. else
  362. LuaDLL.lua_pop(t.L, 1);
  363. //var ty = LuaDLL.lua_type(t.L, -1);
  364. bool ret = LuaDLL.lua_next(t.L, indext) > 0;
  365. if (!ret) iterPhase = 2;
  366. return ret;
  367. }
  368. public void Reset()
  369. {
  370. LuaDLL.lua_getref(t.L, t.Ref);
  371. indext = LuaDLL.lua_gettop(t.L);
  372. }
  373. public void Dispose()
  374. {
  375. if (iterPhase == 1)
  376. LuaDLL.lua_pop(t.L, 2);
  377. LuaDLL.lua_remove(t.L, indext);
  378. }
  379. public TablePair Current
  380. {
  381. get
  382. {
  383. current.key = LuaObject.checkVar(t.L, -2);
  384. current.value = LuaObject.checkVar(t.L, -1);
  385. return current;
  386. }
  387. }
  388. object IEnumerator.Current
  389. {
  390. get
  391. {
  392. return Current;
  393. }
  394. }
  395. }
  396. public IEnumerator<TablePair> GetEnumerator()
  397. {
  398. return new LuaTable.Enumerator(this);
  399. }
  400. IEnumerator IEnumerable.GetEnumerator()
  401. {
  402. return GetEnumerator();
  403. }
  404. }
  405. public class LuaState : IDisposable
  406. {
  407. IntPtr l_;
  408. int mainThread = 0;
  409. internal WeakDictionary<int, LuaDelegate> delgateMap = new WeakDictionary<int, LuaDelegate>();
  410. #if LUA_DEBUG
  411. static Dictionary<string, string> debugStringMap = new Dictionary<string, string>();
  412. #endif
  413. public int cachedDelegateCount
  414. {
  415. get
  416. {
  417. return this.delgateMap.AliveCount;
  418. }
  419. }
  420. public IntPtr L
  421. {
  422. get
  423. {
  424. if (!isMainThread())
  425. {
  426. Logger.LogError("Can't access lua in bg thread");
  427. throw new Exception("Can't access lua in bg thread");
  428. }
  429. if (l_ == IntPtr.Zero)
  430. {
  431. Logger.LogError("LuaState had been destroyed, can't used yet");
  432. throw new Exception("LuaState had been destroyed, can't used yet");
  433. }
  434. return l_;
  435. }
  436. set
  437. {
  438. l_ = value;
  439. }
  440. }
  441. public IntPtr handle
  442. {
  443. get
  444. {
  445. return L;
  446. }
  447. }
  448. public int Top { get { return LuaDLL.lua_gettop(L); } }
  449. public delegate byte[] LoaderDelegate(string fn, ref string absoluteFn);
  450. public delegate void OutputDelegate(string msg);
  451. public delegate void PushVarDelegate(IntPtr l, object o);
  452. public LoaderDelegate loaderDelegate;
  453. public OutputDelegate logDelegate;
  454. public OutputDelegate errorDelegate;
  455. public OutputDelegate warnDelegate;
  456. public delegate void UnRefAction(IntPtr l, int r);
  457. struct UnrefPair
  458. {
  459. public UnRefAction act;
  460. public int r;
  461. }
  462. Queue<UnrefPair> refQueue;
  463. public int PCallCSFunctionRef = 0;
  464. Dictionary<Type, PushVarDelegate> typePushMap = new Dictionary<Type, PushVarDelegate>();
  465. public static Dictionary<IntPtr, LuaState> statemap = new Dictionary<IntPtr, LuaState>();
  466. static IntPtr oldptr = IntPtr.Zero;
  467. static LuaState oldstate = null;
  468. static public LuaCSFunction errorFunc = new LuaCSFunction(errorReport);
  469. int errorRef = 0;
  470. internal LuaFunction newindex_func;
  471. internal LuaFunction index_func;
  472. const string DelgateTable = "__LuaDelegate";
  473. bool openedSluaLib = false;
  474. LuaFunction dumpstack;
  475. public bool isMainThread()
  476. {
  477. return System.Threading.Thread.CurrentThread.ManagedThreadId == mainThread;
  478. }
  479. #if !SLUA_STANDALONE
  480. internal LuaSvrGameObject lgo;
  481. #endif
  482. static public LuaState get(IntPtr l)
  483. {
  484. if (l == oldptr)
  485. return oldstate;
  486. LuaState ls;
  487. if (statemap.TryGetValue(l, out ls))
  488. {
  489. oldptr = l;
  490. oldstate = ls;
  491. return ls;
  492. }
  493. LuaDLL.lua_getglobal(l, "__main_state");
  494. if (LuaDLL.lua_isnil(l, -1))
  495. {
  496. LuaDLL.lua_pop(l, 1);
  497. return null;
  498. }
  499. IntPtr nl = LuaDLL.lua_touserdata(l, -1);
  500. LuaDLL.lua_pop(l, 1);
  501. if (nl != l)
  502. return get(nl);
  503. return null;
  504. }
  505. public void openSluaLib()
  506. {
  507. LuaArray.init(L);
  508. LuaVarObject.init(L);
  509. LuaDLL.lua_newtable(L);
  510. LuaDLL.lua_setglobal(L, DelgateTable);
  511. #if !SLUA_STANDALONE
  512. LuaTimer.reg(L);
  513. LuaCoroutine.reg(L, lgo);
  514. #endif
  515. Lua_SLua_ByteArray.reg(L);
  516. Helper.reg(L);
  517. openedSluaLib = true;
  518. }
  519. public void openExtLib()
  520. {
  521. LuaDLL.luaS_openextlibs(L);
  522. LuaSocketMini.reg(L);
  523. }
  524. public void bindUnity()
  525. {
  526. if (!openedSluaLib)
  527. openSluaLib();
  528. LuaSvr.doBind(L);
  529. LuaValueType.reg(L);
  530. }
  531. public IEnumerator bindUnity(Action<int> _tick, Action complete)
  532. {
  533. if (!openedSluaLib)
  534. openSluaLib();
  535. yield return LuaSvr.doBind(L, _tick, complete);
  536. LuaValueType.reg(L);
  537. }
  538. static public LuaState main
  539. {
  540. get
  541. {
  542. return LuaSvr.mainState;
  543. }
  544. }
  545. public string Name
  546. {
  547. get;
  548. set;
  549. }
  550. public LuaState()
  551. {
  552. if (mainThread == 0)
  553. mainThread = System.Threading.Thread.CurrentThread.ManagedThreadId;
  554. L = LuaDLL.luaL_newstate();
  555. statemap[L] = this;
  556. refQueue = new Queue<UnrefPair>();
  557. ObjectCache.make(L);
  558. LuaDLL.lua_atpanic(L, panicCallback);
  559. LuaDLL.luaL_openlibs(L);
  560. string PCallCSFunction = @"
  561. local assert = assert
  562. local function check(ok,...)
  563. assert(ok, ...)
  564. return ...
  565. end
  566. return function(cs_func)
  567. return function(...)
  568. return check(cs_func(...))
  569. end
  570. end
  571. ";
  572. LuaDLL.lua_dostring(L, PCallCSFunction);
  573. PCallCSFunctionRef = LuaDLL.luaL_ref(L, LuaIndexes.LUA_REGISTRYINDEX);
  574. string newindexfun = @"
  575. local getmetatable=getmetatable
  576. local rawget=rawget
  577. local error=error
  578. local type=type
  579. local function newindex(ud,k,v)
  580. local t=getmetatable(ud)
  581. repeat
  582. local h=rawget(t,k)
  583. if h then
  584. if h[2] then
  585. h[2](ud,v)
  586. return
  587. else
  588. error('property '..k..' is read only')
  589. end
  590. end
  591. t=rawget(t,'__parent')
  592. until t==nil
  593. error('can not find '..k)
  594. end
  595. return newindex
  596. ";
  597. string indexfun = @"
  598. local type=type
  599. local error=error
  600. local rawget=rawget
  601. local getmetatable=getmetatable
  602. local function index(ud,k)
  603. local t=getmetatable(ud)
  604. repeat
  605. local fun=rawget(t,k)
  606. local tp=type(fun)
  607. if tp=='function' then
  608. return fun
  609. elseif tp=='table' then
  610. local f=fun[1]
  611. if f then
  612. return f(ud)
  613. else
  614. error('property '..k..' is write only')
  615. end
  616. end
  617. t = rawget(t,'__parent')
  618. until t==nil
  619. error('Can not find '..k)
  620. end
  621. return index
  622. ";
  623. newindex_func = (LuaFunction)doString(newindexfun);
  624. index_func = (LuaFunction)doString(indexfun);
  625. setupPushVar();
  626. pcall(L, init);
  627. createGameObject();
  628. }
  629. void createGameObject()
  630. {
  631. #if !SLUA_STANDALONE
  632. if (lgo == null
  633. #if UNITY_EDITOR
  634. && UnityEditor.EditorApplication.isPlaying
  635. #endif
  636. )
  637. {
  638. GameObject go = new GameObject("LuaSvrProxy");
  639. lgo = go.AddComponent<LuaSvrGameObject>();
  640. GameObject.DontDestroyOnLoad(go);
  641. lgo.onUpdate = this.tick;
  642. lgo.state = this;
  643. }
  644. #endif
  645. }
  646. void destroyGameObject()
  647. {
  648. #if !SLUA_STANDALONE
  649. #if UNITY_EDITOR
  650. if (UnityEditor.EditorApplication.isPlaying)
  651. #endif
  652. {
  653. if (lgo != null)
  654. {
  655. GameObject go = lgo.gameObject;
  656. GameObject.Destroy(lgo);
  657. GameObject.Destroy(go);
  658. }
  659. }
  660. #endif
  661. }
  662. virtual protected void tick()
  663. {
  664. checkRef();
  665. }
  666. [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
  667. static int init(IntPtr L)
  668. {
  669. LuaDLL.lua_pushlightuserdata(L, L);
  670. LuaDLL.lua_setglobal(L, "__main_state");
  671. LuaDLL.lua_pushcfunction(L, print);
  672. LuaDLL.lua_setglobal(L, "print");
  673. LuaDLL.lua_pushcfunction(L, printerror);
  674. LuaDLL.lua_setglobal(L, "printerror");
  675. LuaDLL.lua_pushcfunction(L, warn);
  676. LuaDLL.lua_setglobal(L, "warn");
  677. #if LUA_DEBUG
  678. LuaDLL.lua_pushcfunction(L, getStringFromMD5);
  679. LuaDLL.lua_setglobal(L, "getStringFromMD5");
  680. #endif
  681. pushcsfunction(L, import);
  682. LuaDLL.lua_setglobal(L, "import");
  683. string resumefunc = @"
  684. local resume = coroutine.resume
  685. local function check(co, ok, err, ...)
  686. if not ok then UnityEngine.Debug.LogError(debug.traceback(co,err)) end
  687. return ok, err, ...
  688. end
  689. coroutine.resume=function(co,...)
  690. return check(co, resume(co,...))
  691. end
  692. ";
  693. // overload resume function for report error
  694. var state = LuaState.get(L);
  695. state.doString(resumefunc);
  696. // https://github.com/pkulchenko/MobDebug/blob/master/src/mobdebug.lua#L290
  697. // Dump only 3 stacks, or it will return null (I don't know why)
  698. string dumpstackfunc = @"
  699. local dumpstack=function()
  700. function vars(f)
  701. local dump = """"
  702. local func = debug.getinfo(f, ""f"").func
  703. local i = 1
  704. local locals = {}
  705. -- get locals
  706. while true do
  707. local name, value = debug.getlocal(f, i)
  708. if not name then break end
  709. if string.sub(name, 1, 1) ~= '(' then
  710. dump = dump .. "" "" .. name .. ""="" .. tostring(value) .. ""\n""
  711. end
  712. i = i + 1
  713. end
  714. -- get varargs (these use negative indices)
  715. i = 1
  716. while true do
  717. local name, value = debug.getlocal(f, -i)
  718. -- `not name` should be enough, but LuaJIT 2.0.0 incorrectly reports `(*temporary)` names here
  719. if not name or name ~= ""(*vararg)"" then break end
  720. dump = dump .. "" "" .. name .. ""="" .. tostring(value) .. ""\n""
  721. i = i + 1
  722. end
  723. -- get upvalues
  724. i = 1
  725. while func do -- check for func as it may be nil for tail calls
  726. local name, value = debug.getupvalue(func, i)
  727. if not name then break end
  728. dump = dump .. "" "" .. name .. ""="" .. tostring(value) .. ""\n""
  729. i = i + 1
  730. end
  731. return dump
  732. end
  733. local dump = """"
  734. for i = 3, 100 do
  735. local source = debug.getinfo(i, ""S"")
  736. if not source then break end
  737. dump = dump .. ""- stack"" .. tostring(i-2) .. ""\n""
  738. dump = dump .. vars(i+1)
  739. if source.what == 'main' then break end
  740. end
  741. return dump
  742. end
  743. return dumpstack
  744. ";
  745. state.dumpstack = state.doString(dumpstackfunc) as LuaFunction;
  746. #if UNITY_ANDROID
  747. // fix android performance drop with JIT on according to luajit mailist post
  748. state.doString("if jit then require('jit.opt').start('sizemcode=256','maxmcode=256') for i=1,1000 do end end");
  749. #endif
  750. pushcsfunction(L, dofile);
  751. LuaDLL.lua_setglobal(L, "dofile");
  752. pushcsfunction(L, loadfile);
  753. LuaDLL.lua_setglobal(L, "loadfile");
  754. pushcsfunction(L, loadfile_env);
  755. LuaDLL.lua_setglobal(L, "loadfile_env");
  756. pushcsfunction(L, loader);
  757. int loaderFunc = LuaDLL.lua_gettop(L);
  758. LuaDLL.lua_getglobal(L, "package");
  759. #if LUA_5_3
  760. LuaDLL.lua_getfield(L, -1, "searchers");
  761. #else
  762. LuaDLL.lua_getfield(L, -1, "loaders");
  763. #endif
  764. int loaderTable = LuaDLL.lua_gettop(L);
  765. // Shift table elements right
  766. for (int e = LuaDLL.lua_rawlen(L, loaderTable) + 1; e > 2; e--)
  767. {
  768. LuaDLL.lua_rawgeti(L, loaderTable, e - 1);
  769. LuaDLL.lua_rawseti(L, loaderTable, e);
  770. }
  771. LuaDLL.lua_pushvalue(L, loaderFunc);
  772. LuaDLL.lua_rawseti(L, loaderTable, 2);
  773. LuaDLL.lua_settop(L, 0);
  774. return 0;
  775. }
  776. void Close()
  777. {
  778. destroyGameObject();
  779. LuaTimer.DeleteAll(L);
  780. if (L != IntPtr.Zero)
  781. {
  782. Logger.Log("Finalizing Lua State.");
  783. // be careful, if you close lua vm, make sure you don't use lua state again,
  784. // comment this line as default for avoid unexpected crash.
  785. LuaDLL.lua_close(L);
  786. ObjectCache.del(L);
  787. ObjectCache.clear();
  788. statemap.Remove(L);
  789. oldptr = IntPtr.Zero;
  790. oldstate = null;
  791. L = IntPtr.Zero;
  792. }
  793. }
  794. public void Dispose()
  795. {
  796. Dispose(true);
  797. System.GC.Collect();
  798. System.GC.WaitForPendingFinalizers();
  799. }
  800. public virtual void Dispose(bool dispose)
  801. {
  802. if (dispose)
  803. {
  804. Close();
  805. }
  806. }
  807. [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
  808. public static int errorReport(IntPtr L)
  809. {
  810. s.Length = 0;
  811. LuaDLL.lua_getglobal(L, "debug");
  812. LuaDLL.lua_getfield(L, -1, "traceback");
  813. LuaDLL.lua_pushvalue(L, 1);
  814. LuaDLL.lua_pushnumber(L, 2);
  815. LuaDLL.lua_call(L, 2, 1);
  816. LuaDLL.lua_remove(L, -2);
  817. s.Append(LuaDLL.lua_tostring(L, -1));
  818. LuaDLL.lua_pop(L, 1);
  819. LuaState state = LuaState.get(L);
  820. state.dumpstack.push(L);
  821. LuaDLL.lua_call(L, 0, 1);
  822. s.Append("\n");
  823. s.Append(LuaDLL.lua_tostring(L, -1));
  824. LuaDLL.lua_pop(L, 1);
  825. string str = s.ToString();
  826. Logger.LogError(str, true);
  827. if (state.errorDelegate != null)
  828. {
  829. state.errorDelegate(str);
  830. }
  831. return 0;
  832. }
  833. [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
  834. internal static int import(IntPtr l)
  835. {
  836. try
  837. {
  838. LuaDLL.luaL_checktype(l, 1, LuaTypes.LUA_TSTRING);
  839. string str = LuaDLL.lua_tostring(l, 1);
  840. string[] ns = str.Split('.');
  841. LuaDLL.lua_pushglobaltable(l);
  842. for (int n = 0; n < ns.Length; n++)
  843. {
  844. LuaDLL.lua_getfield(l, -1, ns[n]);
  845. if (!LuaDLL.lua_istable(l, -1))
  846. {
  847. return LuaObject.error(l, "expect {0} is type table", ns);
  848. }
  849. LuaDLL.lua_remove(l, -2);
  850. }
  851. LuaDLL.lua_pushnil(l);
  852. while (LuaDLL.lua_next(l, -2) != 0)
  853. {
  854. string key = LuaDLL.lua_tostring(l, -2);
  855. LuaDLL.lua_getglobal(l, key);
  856. if (!LuaDLL.lua_isnil(l, -1))
  857. {
  858. LuaDLL.lua_pop(l, 1);
  859. return LuaObject.error(l, "{0} had existed, import can't overload it.", key);
  860. }
  861. LuaDLL.lua_pop(l, 1);
  862. LuaDLL.lua_setglobal(l, key);
  863. }
  864. LuaDLL.lua_pop(l, 1);
  865. LuaObject.pushValue(l, true);
  866. return 1;
  867. }
  868. catch (Exception e)
  869. {
  870. return LuaObject.error(l, e);
  871. }
  872. }
  873. internal static void pcall(IntPtr l, LuaCSFunction f)
  874. {
  875. int err = LuaObject.pushTry(l);
  876. LuaDLL.lua_pushcfunction(l, f);
  877. if (LuaDLL.lua_pcall(l, 0, 0, err) != 0)
  878. {
  879. LuaDLL.lua_pop(l, 1);
  880. }
  881. LuaDLL.lua_remove(l, err);
  882. }
  883. static public bool printTrace = true;
  884. private static StringBuilder s = new StringBuilder();
  885. static string stackString(IntPtr L, int n)
  886. {
  887. s.Length = 0;
  888. LuaDLL.lua_getglobal(L, "tostring");
  889. for (int i = 1; i <= n; i++)
  890. {
  891. if (i > 1)
  892. {
  893. s.Append(" ");
  894. }
  895. LuaDLL.lua_pushvalue(L, -1);
  896. LuaDLL.lua_pushvalue(L, i);
  897. LuaDLL.lua_call(L, 1, 1);
  898. s.Append(LuaDLL.lua_tostring(L, -1));
  899. LuaDLL.lua_pop(L, 1);
  900. }
  901. if (printTrace
  902. #if UNITY_EDITOR
  903. && SLuaSetting.Instance.PrintTrace
  904. #endif
  905. )
  906. {
  907. LuaDLL.lua_getglobal(L, "debug");
  908. LuaDLL.lua_getfield(L, -1, "traceback");
  909. LuaDLL.lua_call(L, 0, 1);
  910. s.Append("\n");
  911. s.Append(LuaDLL.lua_tostring(L, -1));
  912. }
  913. return s.ToString();
  914. }
  915. [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
  916. internal static int print(IntPtr L)
  917. {
  918. #if SOV_RELEASE
  919. return 0;
  920. #endif
  921. int n = LuaDLL.lua_gettop(L);
  922. string str = stackString(L, n);
  923. Logger.Log(str, true);
  924. LuaState state = LuaState.get(L);
  925. if (state.logDelegate != null)
  926. {
  927. state.logDelegate(s.ToString());
  928. }
  929. LuaDLL.lua_settop(L, n);
  930. return 0;
  931. }
  932. // copy from print()
  933. [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
  934. internal static int printerror(IntPtr L)
  935. {
  936. int n = LuaDLL.lua_gettop(L);
  937. string str = stackString(L, n);
  938. Logger.LogError(str, true);
  939. LuaState state = LuaState.get(L);
  940. if (state.errorDelegate != null)
  941. {
  942. state.errorDelegate(s.ToString());
  943. }
  944. LuaDLL.lua_settop(L, n);
  945. return 0;
  946. }
  947. [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
  948. internal static int warn(IntPtr L)
  949. {
  950. int n = LuaDLL.lua_gettop(L);
  951. string str = stackString(L, n);
  952. Logger.LogWarning(str);
  953. LuaState state = LuaState.get(L);
  954. if (state.warnDelegate != null)
  955. {
  956. state.warnDelegate(s.ToString());
  957. }
  958. LuaDLL.lua_settop(L, n);
  959. return 0;
  960. }
  961. [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
  962. internal static int loadfile(IntPtr L)
  963. {
  964. loader(L);
  965. if (LuaDLL.lua_isnil(L, -1))
  966. {
  967. string fileName = LuaDLL.lua_tostring(L, 1);
  968. return LuaObject.error(L, "Can't find {0}", fileName);
  969. }
  970. return 2;
  971. }
  972. [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
  973. internal static int loadfile_env(IntPtr L)
  974. {
  975. LuaState state = LuaState.get(L);
  976. string fileName = LuaDLL.lua_tostring(L, 1);
  977. LuaDLL.luaL_checktype(L, 2, LuaTypes.LUA_TTABLE);
  978. string absoluteFn = "";
  979. byte[] bytes = state.loadFile(fileName, ref absoluteFn);
  980. if (bytes != null)
  981. {
  982. if (LuaDLL.luaL_loadbuffer(L, bytes, bytes.Length, "@" + fileName) == 0)
  983. {
  984. LuaDLL.lua_pushvalue(L, 2);
  985. LuaDLL.lua_setupvalue(L, -2, 1);
  986. LuaObject.pushValue(L, true);
  987. LuaDLL.lua_insert(L, -2);
  988. return 2;
  989. }
  990. else
  991. {
  992. string errstr = LuaDLL.lua_tostring(L, -1);
  993. return LuaObject.error(L, errstr);
  994. }
  995. }
  996. else
  997. {
  998. LuaObject.pushValue(L, true);
  999. LuaDLL.lua_pushnil(L);
  1000. return LuaObject.error(L, "Can't find {0}", fileName);
  1001. }
  1002. }
  1003. [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
  1004. internal static int dofile(IntPtr L)
  1005. {
  1006. int n = LuaDLL.lua_gettop(L);
  1007. loader(L);
  1008. if (!LuaDLL.lua_toboolean(L, -2))
  1009. {
  1010. return 2;
  1011. }
  1012. else
  1013. {
  1014. if (LuaDLL.lua_isnil(L, -1))
  1015. {
  1016. string fileName = LuaDLL.lua_tostring(L, 1);
  1017. return LuaObject.error(L, "Can't find {0}", fileName);
  1018. }
  1019. int k = LuaDLL.lua_gettop(L);
  1020. LuaDLL.lua_call(L, 0, LuaDLL.LUA_MULTRET);
  1021. k = LuaDLL.lua_gettop(L);
  1022. return k - n;
  1023. }
  1024. }
  1025. [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
  1026. static public int panicCallback(IntPtr l)
  1027. {
  1028. string reason = string.Format("unprotected error in call to Lua API ({0})", LuaDLL.lua_tostring(l, -1));
  1029. throw new Exception(reason);
  1030. }
  1031. static public void pushcsfunction(IntPtr L, LuaCSFunction function)
  1032. {
  1033. LuaDLL.lua_getref(L, get(L).PCallCSFunctionRef);
  1034. LuaDLL.lua_pushcclosure(L, function, 0);
  1035. LuaDLL.lua_call(L, 1, 1);
  1036. }
  1037. #if LUA_DEBUG
  1038. [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
  1039. static public int getStringFromMD5(IntPtr L) {
  1040. string str = LuaDLL.lua_tostring(L, -1);
  1041. string destString = "";
  1042. if (debugStringMap.ContainsKey(str))
  1043. {
  1044. destString = debugStringMap[str];
  1045. }
  1046. LuaObject.pushValue(L, destString);
  1047. return 1;
  1048. }
  1049. static public string getStringMD5(string str)
  1050. {
  1051. MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
  1052. byte[] bytes = System.Text.Encoding.UTF8.GetBytes(str);
  1053. byte[] md5Data = md5.ComputeHash(bytes, 0, bytes.Length);
  1054. md5.Clear();
  1055. string destString = "";
  1056. for (int i = 0; i < md5Data.Length; i++)
  1057. {
  1058. destString += System.Convert.ToString(md5Data[i], 16).PadLeft(2, '0');
  1059. }
  1060. destString = destString.PadLeft(32, '0');
  1061. return destString;
  1062. }
  1063. #endif
  1064. public object doString(string str)
  1065. {
  1066. #if LUA_DEBUG
  1067. //get str's md5 string
  1068. string stringMd5 = getStringMD5(str);
  1069. debugStringMap.Add(stringMd5, str);
  1070. return doString(str, stringMd5);
  1071. #else
  1072. return doString(str, "temp buffer");
  1073. #endif
  1074. }
  1075. public object doString(string str, string chunkname)
  1076. {
  1077. byte[] bytes = Encoding.UTF8.GetBytes(str);
  1078. object obj;
  1079. if (doBuffer(bytes, chunkname, out obj))
  1080. return obj;
  1081. return null; ;
  1082. }
  1083. [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
  1084. internal static int loader(IntPtr L)
  1085. {
  1086. LuaState state = LuaState.get(L);
  1087. string fileName = LuaDLL.lua_tostring(L, 1);
  1088. string absoluteFn = "";
  1089. byte[] bytes = state.loadFile(fileName, ref absoluteFn);
  1090. if (bytes != null)
  1091. {
  1092. bytes = CleanUTF8Bom(bytes);
  1093. #if LUA_DEBUG
  1094. if (absoluteFn != "") {
  1095. fileName = absoluteFn;
  1096. }
  1097. #endif
  1098. if (LuaDLL.luaL_loadbuffer(L, bytes, bytes.Length, "@" + fileName) == 0)
  1099. {
  1100. LuaObject.pushValue(L, true);
  1101. LuaDLL.lua_insert(L, -2);
  1102. return 2;
  1103. }
  1104. else
  1105. {
  1106. string errstr = LuaDLL.lua_tostring(L, -1);
  1107. return LuaObject.error(L, errstr);
  1108. }
  1109. }
  1110. LuaObject.pushValue(L, true);
  1111. LuaDLL.lua_pushnil(L);
  1112. return 2;
  1113. }
  1114. public object doFile(string fn)
  1115. {
  1116. string absoluteFn = "";
  1117. byte[] bytes = loadFile(fn, ref absoluteFn);
  1118. if (bytes == null)
  1119. {
  1120. Logger.LogError(string.Format("Can't find {0}", fn));
  1121. return null;
  1122. }
  1123. #if LUA_DEBUG
  1124. if (absoluteFn != "") {
  1125. fn = absoluteFn;
  1126. }
  1127. #endif
  1128. object obj;
  1129. if (doBuffer(bytes, "@" + fn, out obj))
  1130. return obj;
  1131. return null;
  1132. }
  1133. /// <summary>
  1134. /// Ensure remove BOM from bytes
  1135. /// </summary>
  1136. /// <param name="bytes"></param>
  1137. /// <returns></returns>
  1138. public static byte[] CleanUTF8Bom(byte[] bytes)
  1139. {
  1140. if (bytes.Length > 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF)
  1141. {
  1142. var oldBytes = bytes;
  1143. bytes = new byte[bytes.Length - 3];
  1144. Array.Copy(oldBytes, 3, bytes, 0, bytes.Length);
  1145. }
  1146. return bytes;
  1147. }
  1148. public bool doBuffer(byte[] bytes, string fn, out object ret)
  1149. {
  1150. // ensure no utf-8 bom, LuaJIT can read BOM, but Lua cannot!
  1151. bytes = CleanUTF8Bom(bytes);
  1152. ret = null;
  1153. int errfunc = LuaObject.pushTry(L);
  1154. if (LuaDLL.luaL_loadbuffer(L, bytes, bytes.Length, fn) == 0)
  1155. {
  1156. if (LuaDLL.lua_pcall(L, 0, LuaDLL.LUA_MULTRET, errfunc) != 0)
  1157. {
  1158. LuaDLL.lua_pop(L, 2);
  1159. return false;
  1160. }
  1161. LuaDLL.lua_remove(L, errfunc); // pop error function
  1162. ret = topObjects(errfunc - 1);
  1163. return true;
  1164. }
  1165. string err = LuaDLL.lua_tostring(L, -1);
  1166. LuaDLL.lua_pop(L, 2);
  1167. throw new Exception(err);
  1168. }
  1169. #if UNITY_EDITOR
  1170. static TextAsset loadAsset(string fn)
  1171. {
  1172. TextAsset asset;
  1173. #if UNITY_5
  1174. asset = UnityEditor.AssetDatabase.LoadAssetAtPath<TextAsset> (fn);
  1175. #else
  1176. asset = (TextAsset)UnityEditor.AssetDatabase.LoadAssetAtPath(fn, typeof(TextAsset));
  1177. #endif
  1178. return asset;
  1179. }
  1180. #endif
  1181. internal byte[] loadFile(string fn, ref string absoluteFn)
  1182. {
  1183. try
  1184. {
  1185. byte[] bytes;
  1186. if (loaderDelegate != null)
  1187. bytes = loaderDelegate(fn, ref absoluteFn);
  1188. else
  1189. {
  1190. #if !SLUA_STANDALONE
  1191. fn = fn.Replace(".", "/");
  1192. TextAsset asset = null;
  1193. #if UNITY_EDITOR
  1194. if (SLuaSetting.Instance.jitType == JITBUILDTYPE.none)
  1195. {
  1196. asset = (TextAsset)Resources.Load(fn);
  1197. }
  1198. else if (SLuaSetting.Instance.jitType == JITBUILDTYPE.X86)
  1199. {
  1200. asset = loadAsset("Assets/Slua/jit/jitx86/" + fn + ".bytes");
  1201. }
  1202. else if (SLuaSetting.Instance.jitType == JITBUILDTYPE.X64)
  1203. {
  1204. asset = loadAsset("Assets/Slua/jit/jitx64/" + fn + ".bytes");
  1205. }
  1206. else if (SLuaSetting.Instance.jitType == JITBUILDTYPE.GC64)
  1207. {
  1208. asset = loadAsset("Assets/Slua/jit/jitgc64/" + fn + ".bytes");
  1209. }
  1210. #if LUA_DEBUG
  1211. //get asset's absolute path
  1212. string assetFn = UnityEditor.AssetDatabase.GetAssetPath(asset);
  1213. if (assetFn != ""){
  1214. //find out asset path, remove assetFn's first "Asset/"
  1215. int idx = assetFn.IndexOf("/");
  1216. if(idx > 0){
  1217. absoluteFn = Application.dataPath + assetFn.Substring(idx);
  1218. }
  1219. }
  1220. #endif
  1221. #else
  1222. asset = (TextAsset)Resources.Load(fn);
  1223. #endif
  1224. if (asset == null)
  1225. return null;
  1226. bytes = asset.bytes;
  1227. #else
  1228. bytes = File.ReadAllBytes(fn);
  1229. #endif
  1230. }
  1231. return bytes;
  1232. }
  1233. catch (Exception e)
  1234. {
  1235. throw new Exception(e.Message);
  1236. }
  1237. }
  1238. internal object getObject(string key, bool wholekey = false, bool rawget = false)
  1239. {
  1240. LuaDLL.lua_pushglobaltable(L);
  1241. object o;
  1242. if (wholekey)
  1243. o = getObject(new string[] { key }, rawget);
  1244. else
  1245. o = getObject(key.Split(new char[] { '.' }), rawget);
  1246. LuaDLL.lua_pop(L, 1);
  1247. return o;
  1248. }
  1249. internal void setObject(string key, object v, bool wholekey = false, bool rawset = false)
  1250. {
  1251. LuaDLL.lua_pushglobaltable(L);
  1252. if (wholekey)
  1253. setObject(new string[] { key }, v, rawset);
  1254. else
  1255. setObject(key.Split(new char[] { '.' }), v, rawset);
  1256. LuaDLL.lua_pop(L, 1);
  1257. }
  1258. internal object getObject(string[] remainingPath, bool rawget = false)
  1259. {
  1260. object returnValue = null;
  1261. for (int i = 0; i < remainingPath.Length; i++)
  1262. {
  1263. LuaDLL.lua_pushstring(L, remainingPath[i]);
  1264. if (rawget)
  1265. LuaDLL.lua_rawget(L, -2);
  1266. else
  1267. LuaDLL.lua_gettable(L, -2);
  1268. returnValue = this.getObject(L, -1);
  1269. LuaDLL.lua_remove(L, -2);
  1270. if (returnValue == null) break;
  1271. }
  1272. return returnValue;
  1273. }
  1274. internal object getObject(int reference, string field, bool wholekey = false, bool rawget = false)
  1275. {
  1276. int oldTop = LuaDLL.lua_gettop(L);
  1277. LuaDLL.lua_getref(L, reference);
  1278. object returnValue;
  1279. if (wholekey)
  1280. returnValue = getObject(new string[] { field }, rawget);
  1281. else
  1282. returnValue = getObject(field.Split(new char[] { '.' }), rawget);
  1283. LuaDLL.lua_settop(L, oldTop);
  1284. return returnValue;
  1285. }
  1286. internal object getObject(int reference, int index, bool rawget = false)
  1287. {
  1288. if (index >= 1)
  1289. {
  1290. LuaDLL.lua_getref(L, reference);
  1291. if (rawget)
  1292. LuaDLL.lua_rawgeti(L, -1, index);
  1293. else
  1294. {
  1295. LuaDLL.lua_pushinteger(L, index);
  1296. LuaDLL.lua_gettable(L, -2);
  1297. }
  1298. object returnValue = getObject(L, -1);
  1299. LuaDLL.lua_pop(L, 2);
  1300. return returnValue;
  1301. }
  1302. else
  1303. {
  1304. LuaDLL.lua_getref(L, reference);
  1305. LuaDLL.lua_pushinteger(L, index);
  1306. LuaDLL.lua_gettable(L, -2);
  1307. object returnValue = getObject(L, -1);
  1308. LuaDLL.lua_pop(L, 2);
  1309. return returnValue;
  1310. }
  1311. }
  1312. internal object getObject(int reference, object field, bool rawget = false)
  1313. {
  1314. int oldTop = LuaDLL.lua_gettop(L);
  1315. LuaDLL.lua_getref(L, reference);
  1316. LuaObject.pushObject(L, field);
  1317. if (rawget)
  1318. LuaDLL.lua_rawget(L, -2);
  1319. else
  1320. LuaDLL.lua_gettable(L, -2);
  1321. object returnValue = getObject(L, -1);
  1322. LuaDLL.lua_settop(L, oldTop);
  1323. return returnValue;
  1324. }
  1325. internal void setObject(string[] remainingPath, object o, bool rawset = false)
  1326. {
  1327. int top = LuaDLL.lua_gettop(L);
  1328. for (int i = 0; i < remainingPath.Length - 1; i++)
  1329. {
  1330. LuaDLL.lua_pushstring(L, remainingPath[i]);
  1331. if (rawset)
  1332. LuaDLL.lua_rawget(L, -2);
  1333. else
  1334. LuaDLL.lua_gettable(L, -2);
  1335. }
  1336. LuaDLL.lua_pushstring(L, remainingPath[remainingPath.Length - 1]);
  1337. LuaObject.pushVar(L, o);
  1338. if (rawset)
  1339. LuaDLL.lua_rawset(L, -3);
  1340. else
  1341. LuaDLL.lua_settable(L, -3);
  1342. LuaDLL.lua_settop(L, top);
  1343. }
  1344. internal void setObject(int reference, string field, object o, bool wholekey = false, bool rawset = false)
  1345. {
  1346. int oldTop = LuaDLL.lua_gettop(L);
  1347. LuaDLL.lua_getref(L, reference);
  1348. if (wholekey)
  1349. setObject(new string[] { field }, o, rawset);
  1350. else
  1351. setObject(field.Split(new char[] { '.' }), o, rawset);
  1352. LuaDLL.lua_settop(L, oldTop);
  1353. }
  1354. internal void setObject(int reference, int index, object o, bool rawset = false)
  1355. {
  1356. if (index >= 1)
  1357. {
  1358. LuaDLL.lua_getref(L, reference);
  1359. if (rawset)
  1360. {
  1361. LuaObject.pushVar(L, o);
  1362. LuaDLL.lua_rawseti(L, -2, index);
  1363. }
  1364. else
  1365. {
  1366. LuaDLL.lua_pushinteger(L, index);
  1367. LuaObject.pushVar(L, o);
  1368. LuaDLL.lua_settable(L, -3);
  1369. }
  1370. LuaDLL.lua_pop(L, 1);
  1371. }
  1372. else
  1373. {
  1374. LuaDLL.lua_getref(L, reference);
  1375. LuaDLL.lua_pushinteger(L, index);
  1376. LuaObject.pushVar(L, o);
  1377. if (rawset)
  1378. LuaDLL.lua_rawset(L, -3);
  1379. else
  1380. LuaDLL.lua_settable(L, -3);
  1381. LuaDLL.lua_pop(L, 1);
  1382. }
  1383. }
  1384. internal void setObject(int reference, object field, object o, bool rawset)
  1385. {
  1386. int oldTop = LuaDLL.lua_gettop(L);
  1387. LuaDLL.lua_getref(L, reference);
  1388. LuaObject.pushObject(L, field);
  1389. LuaObject.pushObject(L, o);
  1390. LuaDLL.lua_settable(L, -3);
  1391. LuaDLL.lua_settop(L, oldTop);
  1392. }
  1393. internal object topObjects(int from)
  1394. {
  1395. int top = LuaDLL.lua_gettop(L);
  1396. int nArgs = top - from;
  1397. if (nArgs == 0)
  1398. return null;
  1399. else if (nArgs == 1)
  1400. {
  1401. object o = LuaObject.checkVar(L, top);
  1402. LuaDLL.lua_pop(L, 1);
  1403. return o;
  1404. }
  1405. else
  1406. {
  1407. object[] o = new object[nArgs];
  1408. for (int n = 1; n <= nArgs; n++)
  1409. {
  1410. o[n - 1] = LuaObject.checkVar(L, from + n);
  1411. }
  1412. LuaDLL.lua_settop(L, from);
  1413. return o;
  1414. }
  1415. }
  1416. object getObject(IntPtr l, int p)
  1417. {
  1418. p = LuaDLL.lua_absindex(l, p);
  1419. return LuaObject.checkVar(l, p);
  1420. }
  1421. public LuaFunction getFunction(string key)
  1422. {
  1423. return (LuaFunction)this[key];
  1424. }
  1425. public LuaTable getTable(string key)
  1426. {
  1427. return (LuaTable)this[key];
  1428. }
  1429. public object this[string path]
  1430. {
  1431. get
  1432. {
  1433. return this.getObject(path);
  1434. }
  1435. set
  1436. {
  1437. this.setObject(path, value);
  1438. }
  1439. }
  1440. public void gcRef(UnRefAction act, int r)
  1441. {
  1442. UnrefPair u = new UnrefPair();
  1443. u.act = act;
  1444. u.r = r;
  1445. lock (refQueue)
  1446. {
  1447. refQueue.Enqueue(u);
  1448. }
  1449. }
  1450. public void checkRef()
  1451. {
  1452. int cnt = 0;
  1453. // fix il2cpp lock issue on iOS
  1454. lock (refQueue)
  1455. {
  1456. cnt = refQueue.Count;
  1457. }
  1458. var l = L;
  1459. for (int n = 0; n < cnt; n++)
  1460. {
  1461. UnrefPair u;
  1462. lock (refQueue)
  1463. {
  1464. u = refQueue.Dequeue();
  1465. }
  1466. u.act(l, u.r);
  1467. }
  1468. }
  1469. public void regPushVar(Type t, PushVarDelegate d) { typePushMap[t] = d; }
  1470. public bool tryGetTypePusher(Type t, out PushVarDelegate d) { return typePushMap.TryGetValue(t, out d); }
  1471. void setupPushVar()
  1472. {
  1473. typePushMap[typeof(float)] = (IntPtr L, object o) =>
  1474. {
  1475. LuaDLL.lua_pushnumber(L, (float)o);
  1476. };
  1477. typePushMap[typeof(double)] = (IntPtr L, object o) =>
  1478. {
  1479. LuaDLL.lua_pushnumber(L, (double)o);
  1480. };
  1481. typePushMap[typeof(int)] =
  1482. (IntPtr L, object o) =>
  1483. {
  1484. LuaDLL.lua_pushinteger(L, (int)o);
  1485. };
  1486. typePushMap[typeof(uint)] =
  1487. (IntPtr L, object o) =>
  1488. {
  1489. LuaDLL.lua_pushnumber(L, Convert.ToUInt32(o));
  1490. };
  1491. typePushMap[typeof(short)] =
  1492. (IntPtr L, object o) =>
  1493. {
  1494. LuaDLL.lua_pushinteger(L, (short)o);
  1495. };
  1496. typePushMap[typeof(ushort)] =
  1497. (IntPtr L, object o) =>
  1498. {
  1499. LuaDLL.lua_pushinteger(L, (ushort)o);
  1500. };
  1501. typePushMap[typeof(sbyte)] =
  1502. (IntPtr L, object o) =>
  1503. {
  1504. LuaDLL.lua_pushinteger(L, (sbyte)o);
  1505. };
  1506. typePushMap[typeof(byte)] =
  1507. (IntPtr L, object o) =>
  1508. {
  1509. LuaDLL.lua_pushinteger(L, (byte)o);
  1510. };
  1511. typePushMap[typeof(Int64)] =
  1512. typePushMap[typeof(UInt64)] =
  1513. (IntPtr L, object o) =>
  1514. {
  1515. #if LUA_5_3
  1516. LuaDLL.lua_pushinteger(L, System.Convert.ToInt64(o));
  1517. #else
  1518. LuaDLL.lua_pushnumber(L, System.Convert.ToDouble(o));
  1519. #endif
  1520. };
  1521. typePushMap[typeof(string)] = (IntPtr L, object o) =>
  1522. {
  1523. LuaDLL.lua_pushstring(L, (string)o);
  1524. };
  1525. typePushMap[typeof(bool)] = (IntPtr L, object o) =>
  1526. {
  1527. LuaDLL.lua_pushboolean(L, (bool)o);
  1528. };
  1529. typePushMap[typeof(LuaTable)] =
  1530. typePushMap[typeof(LuaFunction)] =
  1531. typePushMap[typeof(LuaThread)] =
  1532. (IntPtr L, object o) =>
  1533. {
  1534. ((LuaVar)o).push(L);
  1535. };
  1536. typePushMap[typeof(LuaCSFunction)] = (IntPtr L, object o) =>
  1537. {
  1538. LuaObject.pushValue(L, (LuaCSFunction)o);
  1539. };
  1540. #if !SLUA_STANDALONE
  1541. regPushVar(typeof(UnityEngine.Vector2), (IntPtr L, object o) => { LuaObject.pushValue(L, (UnityEngine.Vector2)o); });
  1542. regPushVar(typeof(UnityEngine.Vector3), (IntPtr L, object o) => { LuaObject.pushValue(L, (UnityEngine.Vector3)o); });
  1543. regPushVar(typeof(UnityEngine.Vector4), (IntPtr L, object o) => { LuaObject.pushValue(L, (UnityEngine.Vector4)o); });
  1544. regPushVar(typeof(UnityEngine.Quaternion), (IntPtr L, object o) => { LuaObject.pushValue(L, (UnityEngine.Quaternion)o); });
  1545. regPushVar(typeof(UnityEngine.Color), (IntPtr L, object o) => { LuaObject.pushValue(L, (UnityEngine.Color)o); });
  1546. #endif
  1547. }
  1548. public int pushTry(IntPtr L)
  1549. {
  1550. if (errorRef == 0)
  1551. {
  1552. LuaDLL.lua_pushcfunction(L, LuaState.errorFunc);
  1553. LuaDLL.lua_pushvalue(L, -1);
  1554. errorRef = LuaDLL.luaL_ref(L, LuaIndexes.LUA_REGISTRYINDEX);
  1555. }
  1556. else
  1557. {
  1558. LuaDLL.lua_getref(L, errorRef);
  1559. }
  1560. return LuaDLL.lua_gettop(L);
  1561. }
  1562. public object run(string entry)
  1563. {
  1564. using (LuaFunction func = getFunction(entry))
  1565. {
  1566. if (func != null)
  1567. return func.call();
  1568. }
  1569. return null;
  1570. }
  1571. }
  1572. }