LuaDLL.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  1. #define TOLUA
  2. /*
  3. #########
  4. ############
  5. #############
  6. ## ###########
  7. ### ###### #####
  8. ### ####### ####
  9. ### ########## ####
  10. #### ########### ####
  11. #### ########### #####
  12. ##### ### ######## #####
  13. ##### ### ######## ######
  14. ###### ### ########### ######
  15. ###### #### ############## ######
  16. ####### ##################### ######
  17. ####### ###################### ######
  18. ####### ###### ################# ######
  19. ####### ###### ###### ######### ######
  20. ####### ## ###### ###### ######
  21. ####### ###### ##### #####
  22. ###### ##### ##### ####
  23. ##### #### ##### ###
  24. ##### ### ### #
  25. ### ### ###
  26. ## ### ###
  27. __________#_______####_______####______________
  28. 我们的未来没有BUG
  29. * ==============================================================================
  30. * Filename: LuaDLL.cs
  31. * Created: 2018/7/13 14:29:22
  32. * Author: エル・プサイ・コングリィ
  33. * Purpose:
  34. * ==============================================================================
  35. */
  36. #if UNITY_EDITOR || USE_LUA_PROFILER
  37. using System;
  38. using System.Reflection;
  39. using System.Runtime.InteropServices;
  40. using System.Text;
  41. using MikuHook;
  42. #if TOLUA
  43. using OldLuaDLL = LuaInterface.LuaDLL;
  44. #elif XLUA
  45. using OldLuaDLL = XLua.LuaDLL.Lua;
  46. #elif SLUA
  47. using OldLuaDLL = SLua.LuaDLL;
  48. #else
  49. using OldLuaDLL = MikuLuaProfiler.LuaDLL;
  50. #endif
  51. namespace MikuLuaProfiler
  52. {
  53. #region 通用结构体
  54. public enum LuaGCOptions
  55. {
  56. LUA_GCSTOP = 0,
  57. LUA_GCRESTART = 1,
  58. LUA_GCCOLLECT = 2,
  59. LUA_GCCOUNT = 3,
  60. LUA_GCCOUNTB = 4,
  61. LUA_GCSTEP = 5,
  62. LUA_GCSETPAUSE = 6,
  63. LUA_GCSETSTEPMUL = 7,
  64. }
  65. public class LuaIndexes
  66. {
  67. #if XLUA
  68. public static int LUA_REGISTRYINDEX { get; set; }
  69. #else
  70. public static int LUA_REGISTRYINDEX = -10000;
  71. public static int LUA_ENVIRONINDEX = -10001;
  72. public static int LUA_GLOBALSINDEX = -10002;
  73. #endif
  74. }
  75. [AttributeUsage(AttributeTargets.Method)]
  76. public sealed class MonoPInvokeCallbackAttribute : Attribute
  77. {
  78. public MonoPInvokeCallbackAttribute(Type type)
  79. {
  80. }
  81. }
  82. #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN
  83. [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  84. public delegate int LuaCSFunction(IntPtr luaState);
  85. #else
  86. public delegate int LuaCSFunction(IntPtr luaState);
  87. #endif
  88. #endregion
  89. public class LuaDLL
  90. {
  91. #if !UNITY_EDITOR && UNITY_IPHONE
  92. const string LUADLL = "__Internal";
  93. #else
  94. #if TOLUA
  95. const string LUADLL = "tolua";
  96. #elif XLUA
  97. const string LUADLL = "xlua";
  98. #elif SLUA
  99. const string LUADLL = "slua";
  100. #else
  101. const string LUADLL = "lua";
  102. #endif
  103. #endif
  104. #region index
  105. #if XLUA
  106. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  107. public static extern int xlua_getglobal(IntPtr L, string name);
  108. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  109. public static extern int xlua_setglobal(IntPtr L, string name);
  110. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  111. public static extern int xlua_get_registry_index();
  112. #endif
  113. public static void lua_setglobal(IntPtr luaState, string name)
  114. {
  115. #if TOLUA || SLUA
  116. lua_setfield(luaState, LuaIndexes.LUA_GLOBALSINDEX, name);
  117. #elif XLUA
  118. xlua_setglobal(luaState, name);
  119. #endif
  120. }
  121. public static void lua_getglobal(IntPtr luaState, string name)
  122. {
  123. #if TOLUA || SLUA
  124. lua_getfield(luaState, LuaIndexes.LUA_GLOBALSINDEX, name);
  125. #elif XLUA
  126. xlua_getglobal(luaState, name);
  127. #endif
  128. }
  129. public delegate void tolua_getref_fun(IntPtr luaState, int reference);
  130. public static void lua_getref(IntPtr luaState, int reference)
  131. {
  132. lua_rawgeti(luaState, LuaIndexes.LUA_REGISTRYINDEX, reference);
  133. }
  134. public static void lua_unref(IntPtr luaState, int reference)
  135. {
  136. luaL_unref(luaState, LuaIndexes.LUA_REGISTRYINDEX, reference);
  137. }
  138. #endregion
  139. #region 通用操作
  140. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  141. public static extern IntPtr luaL_newstate();
  142. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  143. public static extern void lua_close(IntPtr luaState);
  144. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  145. public static extern int lua_gettop(IntPtr luaState);
  146. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  147. public static extern void lua_settop(IntPtr luaState, int top);
  148. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  149. public static extern void lua_pushvalue(IntPtr luaState, int idx);
  150. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  151. public static extern void lua_remove(IntPtr luaState, int idx);
  152. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  153. public static extern void lua_insert(IntPtr luaState, int idx);
  154. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  155. public static extern LuaTypes lua_type(IntPtr luaState, int index);
  156. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  157. public static extern double lua_tonumber(IntPtr luaState, int idx);
  158. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  159. public static extern void lua_pushnil(IntPtr luaState);
  160. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  161. public static extern void lua_pushnumber(IntPtr luaState, double number);
  162. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  163. public static extern void lua_pushstring(IntPtr luaState, string str); //[-0, +1, m]
  164. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  165. public static extern void lua_pushboolean(IntPtr luaState, int value);
  166. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  167. public static extern void lua_getfield(IntPtr L, int idx, string key);
  168. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  169. public static extern void lua_rawget(IntPtr luaState, int idx);
  170. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  171. public static extern void lua_rawgeti(IntPtr luaState, int idx, int n);
  172. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  173. public static extern void lua_createtable(IntPtr luaState, int narr, int nrec); //[-0, +1, m]
  174. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  175. public static extern void lua_setfield(IntPtr L, int idx, string key);
  176. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  177. public static extern void lua_rawset(IntPtr luaState, int idx); //[-2, +0, m]
  178. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  179. public static extern int lua_pcall(IntPtr luaState, int nArgs, int nResults, int errfunc);
  180. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  181. public static extern int lua_gc(IntPtr luaState, LuaGCOptions what, int data); //[-0, +0, e]
  182. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  183. public static extern int lua_next(IntPtr luaState, int index); //[-1, +(2|0), e]
  184. public static int lua_getobjlen(IntPtr luaState, int stackPos)
  185. {
  186. #if XLUA
  187. return (int)xlua_objlen(luaState, stackPos);
  188. #else
  189. return lua_objlen(luaState, stackPos);
  190. #endif
  191. }
  192. #if XLUA
  193. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  194. public static extern uint xlua_objlen(IntPtr L, int stackPos);
  195. #else
  196. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  197. public static extern int lua_objlen(IntPtr luaState, int stackPos);
  198. #endif
  199. public static void lua_pop(IntPtr luaState, int amount)
  200. {
  201. LuaDLL.lua_settop(luaState, -(amount) - 1);
  202. }
  203. public static void lua_newtable(IntPtr luaState)
  204. {
  205. LuaDLL.lua_createtable(luaState, 0, 0);
  206. }
  207. public static bool lua_isfunction(IntPtr luaState, int n)
  208. {
  209. return lua_type(luaState, n) == LuaTypes.LUA_TFUNCTION;
  210. }
  211. public static bool lua_isnil(IntPtr luaState, int n)
  212. {
  213. return lua_type(luaState, n) == LuaTypes.LUA_TNIL;
  214. }
  215. public static bool lua_istable(IntPtr luaState, int n)
  216. {
  217. return lua_type(luaState, n) == LuaTypes.LUA_TTABLE;
  218. }
  219. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  220. public static extern void luaL_openlibs(IntPtr luaState);
  221. public static void luaL_initlibs(IntPtr luaState)
  222. {
  223. luaL_openlibs(luaState);
  224. #if XLUA
  225. LuaIndexes.LUA_REGISTRYINDEX = xlua_get_registry_index();
  226. LuaLib.DoString(luaState, env_script);
  227. #endif
  228. }
  229. #region script
  230. const string env_script = @"
  231. local function getfunction(level)
  232. local info = debug.getinfo(level + 1, 'f')
  233. return info and info.func
  234. end
  235. function setfenv(fn, env)
  236. if type(fn) == 'number' then fn = getfunction(fn + 1) end
  237. local i = 1
  238. while true do
  239. local name = debug.getupvalue(fn, i)
  240. if name == '_ENV' then
  241. debug.upvaluejoin(fn, i, (function()
  242. return env
  243. end), 1)
  244. break
  245. elseif not name then
  246. break
  247. end
  248. i = i + 1
  249. end
  250. return fn
  251. end
  252. function getfenv(fn)
  253. if type(fn) == 'number' then fn = getfunction(fn + 1) end
  254. local i = 1
  255. while true do
  256. local name, val = debug.getupvalue(fn, i)
  257. if name == '_ENV' then
  258. return val
  259. elseif not name then
  260. break
  261. end
  262. i = i + 1
  263. end
  264. end
  265. ";
  266. #endregion
  267. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  268. public static extern int luaL_ref(IntPtr luaState, int t); //[-1, +0, m]
  269. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  270. public static extern void luaL_unref(IntPtr luaState, int registryIndex, int reference);
  271. #if TOLUA || SLUA || XLUA
  272. #if TOLUA
  273. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  274. #elif SLUA
  275. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "luaLS_loadbuffer")]
  276. #elif XLUA
  277. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "xluaL_loadbuffer")]
  278. #endif
  279. public static extern int luaL_loadbuffer(IntPtr luaState, byte[] buff, IntPtr size, string name);
  280. #else
  281. public static int luaL_loadbuffer(IntPtr luaState, byte[] buff, IntPtr size, string name)
  282. {
  283. return 1;
  284. }
  285. #endif
  286. public static string lua_tostring(IntPtr luaState, int index)
  287. {
  288. IntPtr len;
  289. IntPtr str = lua_tolstring(luaState, index, out len);
  290. if (str != IntPtr.Zero)
  291. {
  292. return lua_ptrtostring(str, (int)len);
  293. }
  294. return null;
  295. }
  296. public static string lua_ptrtostring(IntPtr str, int len)
  297. {
  298. string ss = Marshal.PtrToStringAnsi(str, len);
  299. if (ss == null)
  300. {
  301. byte[] buffer = new byte[len];
  302. Marshal.Copy(str, buffer, 0, len);
  303. return Encoding.UTF8.GetString(buffer);
  304. }
  305. return ss;
  306. }
  307. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  308. public static extern IntPtr lua_tolstring(IntPtr luaState, int index, out IntPtr strLen);
  309. [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
  310. public static extern void lua_pushcclosure(IntPtr L, IntPtr fn, int nup);
  311. public static void lua_pushstdcallcfunction(IntPtr luaState, LuaCSFunction func)
  312. {
  313. IntPtr fn = Marshal.GetFunctionPointerForDelegate(func);
  314. lua_pushcclosure(luaState, fn, 0);
  315. }
  316. #endregion
  317. #region mono hook
  318. private static CSharpMethodHooker luaL_newstate_hooker;
  319. private static CSharpMethodHooker lua_close_hooker;
  320. private static CSharpMethodHooker lua_load_buffer_hooker;
  321. private static CSharpMethodHooker luaL_ref_hooker;
  322. private static CSharpMethodHooker luaL_unref_hooker;
  323. #if TOLUA
  324. private static CSharpMethodHooker tolua_ref_hooker;
  325. private static CSharpMethodHooker tolua_unref_hooker;
  326. #endif
  327. private static bool m_hooked = false;
  328. private static object m_Lock = 1;
  329. public static void Install()
  330. {
  331. #if TOLUA || XLUA || SLUA
  332. if (m_hooked) return;
  333. Type oldType = typeof(OldLuaDLL);
  334. Type replaceType = typeof(LuaDLL);
  335. if (luaL_newstate_hooker == null)
  336. {
  337. luaL_newstate_hooker = BindHook(oldType, replaceType, "luaL_newstate", "luaL_newstate_replace");
  338. }
  339. if (lua_close_hooker == null)
  340. {
  341. lua_close_hooker = BindHook(oldType, replaceType, "lua_close", "lua_close_replace");
  342. }
  343. if (luaL_ref_hooker == null)
  344. {
  345. luaL_ref_hooker = BindHook(oldType, replaceType, "luaL_ref", "luaL_ref_replace");
  346. }
  347. if (luaL_unref_hooker == null)
  348. {
  349. luaL_unref_hooker = BindHook(oldType, replaceType, "luaL_unref", "luaL_unref_replace");
  350. }
  351. if (lua_load_buffer_hooker == null)
  352. {
  353. #if TOLUA
  354. lua_load_buffer_hooker = BindHook(oldType, replaceType, "tolua_loadbuffer", "luaL_loadbuffer_replace");
  355. #elif XLUA
  356. lua_load_buffer_hooker = BindHook(oldType, replaceType, "xluaL_loadbuffer", "luaL_loadbuffer_replace");
  357. #elif SLUA
  358. oldType = typeof(SLua.LuaDLLWrapper);
  359. lua_load_buffer_hooker = BindHook(oldType, replaceType, "luaLS_loadbuffer", "luaL_loadbuffer_replace");
  360. #endif
  361. }
  362. #if TOLUA
  363. if (tolua_ref_hooker == null)
  364. {
  365. MethodInfo oldFun = oldType.GetMethod("toluaL_ref");
  366. MethodInfo replaceFun = replaceType.GetMethod("toluaL_ref_replace");
  367. MethodInfo proxyFun = replaceType.GetMethod("toluaL_ref_proxy");
  368. tolua_ref_hooker = CSharpMethodHooker.HookCSMethod(oldFun, replaceFun, proxyFun);
  369. }
  370. if (tolua_unref_hooker == null)
  371. {
  372. MethodInfo oldFun = oldType.GetMethod("toluaL_unref");
  373. MethodInfo replaceFun = replaceType.GetMethod("toluaL_unref_replace");
  374. MethodInfo proxyFun = replaceType.GetMethod("toluaL_unref_proxy");
  375. tolua_unref_hooker = CSharpMethodHooker.HookCSMethod(oldFun, replaceFun, proxyFun);
  376. }
  377. #endif
  378. m_hooked = true;
  379. #endif
  380. }
  381. public static void UnInstall()
  382. {
  383. #if TOLUA || XLUA || SLUA
  384. if (luaL_newstate_hooker != null)
  385. {
  386. luaL_newstate_hooker.Uninstall();
  387. luaL_newstate_hooker = null;
  388. }
  389. if (lua_close_hooker != null)
  390. {
  391. lua_close_hooker.Uninstall();
  392. lua_close_hooker = null;
  393. }
  394. if (lua_load_buffer_hooker != null)
  395. {
  396. lua_load_buffer_hooker.Uninstall();
  397. lua_load_buffer_hooker = null;
  398. }
  399. if (luaL_ref_hooker != null)
  400. {
  401. luaL_ref_hooker.Uninstall();
  402. luaL_ref_hooker = null;
  403. }
  404. if (luaL_unref_hooker != null)
  405. {
  406. luaL_unref_hooker.Uninstall();
  407. luaL_unref_hooker = null;
  408. }
  409. #if TOLUA
  410. if (tolua_ref_hooker != null)
  411. {
  412. tolua_ref_hooker.Uninstall();
  413. tolua_ref_hooker = null;
  414. }
  415. if (tolua_unref_hooker != null)
  416. {
  417. tolua_unref_hooker.Uninstall();
  418. tolua_unref_hooker = null;
  419. }
  420. #endif
  421. m_hooked = false;
  422. #endif
  423. }
  424. private static CSharpMethodHooker BindHook(Type oldType, Type replaceType, string oldName, string replaceName)
  425. {
  426. MethodInfo oldFun = null;
  427. if (oldName == "luaL_ref")
  428. {
  429. oldFun = oldType.GetMethod(oldName, new Type[] { typeof(IntPtr), typeof(int) });
  430. }
  431. else if (oldName == "luaL_unref")
  432. {
  433. oldFun = oldType.GetMethod(oldName, new Type[] { typeof(IntPtr), typeof(int), typeof(int) });
  434. }
  435. else
  436. {
  437. oldFun = oldType.GetMethod(oldName);
  438. }
  439. MethodInfo replaceFun = replaceType.GetMethod(replaceName);
  440. CSharpMethodHooker result = CSharpMethodHooker.HookCSMethod(oldFun, replaceFun);
  441. return result;
  442. }
  443. public static IntPtr luaL_newstate_replace()
  444. {
  445. lock (m_Lock)
  446. {
  447. IntPtr intPtr = LuaDLL.luaL_newstate();
  448. LuaProfiler.mainL = intPtr;
  449. MikuLuaProfilerLuaProfilerWrap.__Register(intPtr);
  450. return intPtr;
  451. }
  452. }
  453. public static void lua_close_replace(IntPtr luaState)
  454. {
  455. lock (m_Lock)
  456. {
  457. if (LuaProfiler.mainL == luaState)
  458. {
  459. LuaProfiler.mainL = IntPtr.Zero;
  460. }
  461. LuaDLL.lua_close(luaState);
  462. }
  463. }
  464. public static int luaL_loadbuffer_replace(IntPtr luaState, byte[] buff, int size, string name)
  465. {
  466. #if TOLUA || XLUA || SLUA
  467. lock (m_Lock)
  468. {
  469. buff = LuaHook.Hookloadbuffer(luaState, buff, name);
  470. return LuaDLL.luaL_loadbuffer(luaState, buff, (IntPtr)(buff.Length), name);
  471. }
  472. #else
  473. return 1;
  474. #endif
  475. }
  476. public static int luaL_ref_replace(IntPtr luaState, int t)
  477. {
  478. lock (m_Lock)
  479. {
  480. int num = LuaDLL.luaL_ref(luaState, t);
  481. LuaHook.HookRef(luaState, num);
  482. return num;
  483. }
  484. }
  485. public static void luaL_unref_replace(IntPtr luaState, int registryIndex, int reference)
  486. {
  487. lock (m_Lock)
  488. {
  489. LuaHook.HookUnRef(luaState, reference);
  490. LuaDLL.luaL_unref(luaState, registryIndex, reference);
  491. }
  492. }
  493. public static tolua_getref_fun tolua_Getref_Fun = new tolua_getref_fun(toluaL_get_ref);
  494. public static void toluaL_get_ref(IntPtr L, int reference)
  495. {
  496. // _R[5] table放到栈顶
  497. lua_getref(L, 5);
  498. lua_rawgeti(L, -1, reference);
  499. }
  500. public static int toluaL_ref_replace(IntPtr L)
  501. {
  502. lock (m_Lock)
  503. {
  504. int num = toluaL_ref_proxy(L);
  505. LuaHook.HookRef(L, num, tolua_Getref_Fun);
  506. return num;
  507. }
  508. }
  509. public static int toluaL_ref_proxy(IntPtr L)
  510. {
  511. for (int i = 0, imax = 250;i<imax;i++)
  512. {
  513. UnityEngine.Debug.Log("fuck misaka");
  514. }
  515. return 0;
  516. }
  517. public static void toluaL_unref_replace(IntPtr L, int reference)
  518. {
  519. lock (m_Lock)
  520. {
  521. LuaHook.HookUnRef(L, reference, tolua_Getref_Fun);
  522. toluaL_unref_proxy(L, reference);
  523. }
  524. }
  525. public static void toluaL_unref_proxy(IntPtr L, int reference)
  526. {
  527. for (int i = 0, imax = 250; i < imax; i++)
  528. {
  529. UnityEngine.Debug.Log("fuck misaka");
  530. }
  531. }
  532. #endregion
  533. }
  534. }
  535. #endif