KLuaScript.cpp
上传用户:dzyhzl
上传日期:2019-04-29
资源大小:56270k
文件大小:17k
源码类别:

模拟服务器

开发平台:

C/C++

  1. //---------------------------------------------------------------------------
  2. // Sword3 Engine (c) 1999-2000 by Kingsoft
  3. // 
  4. // File: KLuaScript.cpp
  5. // Date: 2001-9-13 10:33:29
  6. // Code: Romandou
  7. // Desc:
  8. //---------------------------------------------------------------------------
  9. #include "KWin32.h"
  10. #include "KDebug.h"
  11. #include "KPakFile.h"
  12. #include "KLuaScript.h"
  13. #include "LuaLib.h"
  14. #include "KMemClass.h"
  15. //---------------------------------------------------------------------------
  16. // 函数: KLuaScript::KLuaScript
  17. // 功能:
  18. // 参数: void
  19. // 返回:
  20. //---------------------------------------------------------------------------
  21. KLuaScript::KLuaScript(void)
  22. {
  23. m_LuaState = lua_open(100);
  24. if (m_LuaState == NULL)
  25. {
  26. ScriptError(LUA_CREATE_ERROR);
  27. m_IsRuning = FALSE;
  28. return ;
  29. }
  30. m_IsRuning = TRUE;
  31. m_szScriptName[0] = '';
  32. }
  33. //---------------------------------------------------------------------------
  34. // 函数: KLuaScript::KLuaScript
  35. // 功能:
  36. // 参数: int StackSize
  37. // 返回:
  38. //---------------------------------------------------------------------------
  39. KLuaScript::KLuaScript(int StackSize = 0)
  40. {
  41. m_LuaState = Lua_Create(StackSize);
  42. if (m_LuaState == NULL )
  43. {
  44. ScriptError(LUA_CREATE_ERROR);
  45. m_IsRuning = FALSE;
  46. return ;
  47. }
  48. m_IsRuning = TRUE;
  49. m_szScriptName[0] = '';
  50. }
  51. //---------------------------------------------------------------------------
  52. // 函数: KLuaScript::~KLuaScript
  53. // 功能:
  54. // 参数: void
  55. // 返回:
  56. //---------------------------------------------------------------------------
  57. KLuaScript::~KLuaScript(void)
  58. {
  59. Exit();
  60. }
  61. //---------------------------------------------------------------------------
  62. // 函数: KLuaScript::LoadBuffer()
  63. // 功能:
  64. // 参数: PBYTE pBuffer
  65. // 参数: DWORD dwLen
  66. // 返回: BOOL 
  67. //---------------------------------------------------------------------------
  68. BOOL KLuaScript::LoadBuffer(PBYTE pBuffer, DWORD dwLen )
  69. {
  70. if (dwLen < 0)
  71. {
  72. ScriptError(LUA_SCRIPT_LEN_ERROR);
  73. return FALSE;
  74. }
  75. if (Lua_CompileBuffer(m_LuaState, (char *) pBuffer, dwLen, NULL) != 0)
  76. {
  77. ScriptError(LUA_SCRIPT_COMPILE_ERROR);
  78. return FALSE;
  79. }
  80. return TRUE;
  81. }
  82. //---------------------------------------------------------------------------
  83. // 函数: KLuaScript::Load
  84. // 功能:
  85. // 参数: LPSTR Filename
  86. // 返回: BOOL 
  87. //---------------------------------------------------------------------------
  88. BOOL KLuaScript::Load(char * Filename)
  89. {
  90. KPakFile File;
  91. DWORD Size;
  92. // open file
  93. if (!File.Open(Filename)) return FALSE;
  94. // get file size
  95. Size = File.Size();
  96. KMemClass Memory;
  97. // alloc memory
  98. if (! Memory.Alloc(Size + 4))
  99. return FALSE;
  100. // read file
  101. if (File.Read(Memory.GetMemPtr(), Size) != Size)
  102. return FALSE;
  103. char * pszMem = (char *)Memory.GetMemPtr();
  104. pszMem[Size + 1] = 0;
  105. File.Close();
  106. try
  107. {
  108. if (!LoadBuffer((PBYTE)Memory.GetMemPtr(), Size ))
  109. {
  110. ScriptError(LUA_SCRIPT_COMPILE_ERROR);
  111. return FALSE;
  112. }
  113. }
  114. catch(...)
  115. {
  116. printf("Load Script %s 出现异常,请检查!!n", Filename);
  117. return FALSE;
  118. }
  119. if (!ExecuteCode()) return FALSE;
  120. return TRUE;
  121. }
  122. //---------------------------------------------------------------------------
  123. // 函数: KLuaScript::Execute
  124. // 功能:
  125. // 返回: BOOL 
  126. //---------------------------------------------------------------------------
  127. BOOL KLuaScript::Execute()
  128. {
  129. if (m_IsRuning && m_LuaState)
  130. return CallFunction(MAINFUNCTIONNAME,0,"");
  131. return FALSE;
  132. }
  133. //---------------------------------------------------------------------------
  134. // 函数: KLuaScript::ExecuteCode
  135. // 功能:
  136. // 返回: BOOL 
  137. //---------------------------------------------------------------------------
  138. BOOL KLuaScript::ExecuteCode()
  139. {
  140. if (!(m_IsRuning && m_LuaState))
  141. {
  142. ScriptError(LUA_SCRIPT_EXECUTE_ERROR);
  143. //if (!ExecuteCode()) return FALSE; ZHANGPENG 发现这里可能有错
  144. return FALSE;
  145. }
  146. int state;
  147. if (state = Lua_Execute(m_LuaState) != 0)
  148. {
  149. ScriptError(LUA_SCRIPT_EXECUTE_ERROR, state);
  150. return FALSE;
  151. }
  152. return TRUE;
  153. }
  154. //---------------------------------------------------------------------------
  155. // 函数: KLuaScript::CallFunction
  156. // 功能: 调用Lua脚本内的函数
  157. // 参数: LPSTR cFuncName
  158. // 参数: int nResults
  159. // 参数: LPSTR cFormat  调用时所传参数的类型 
  160. // n:数字型(double) d:整形(int) s:字符串型 f:C函数型  n:Nil v:Value p:Point
  161. //        v形为Lua支持的,参数为整形的数index,指明将index所指堆栈的变量作为
  162. //  该函数的调用参数。
  163. // 注意:由于该函数有不定参数…,对于数字,系统并不确定数是以double还是以int
  164. //  存在,两种保存形式是不同的。因此需要注意当传入的数是整形时,格式符应用d
  165. //  而不能用n,或者强行改变为double形。否则会出现计算的错误。
  166. //   
  167. // 参数: ...
  168. // 返回: BOOL 
  169. //---------------------------------------------------------------------------
  170. BOOL KLuaScript::CallFunction(LPSTR cFuncName, int nResults, LPSTR cFormat, va_list vlist)
  171. {
  172. double nNumber;
  173. char * cString = NULL;
  174. void * pPoint = NULL;
  175. Lua_CFunction CFunc;
  176. int i=0;
  177. int nArgnum = 0;
  178. int nIndex = 0;
  179. int nRetcode; //调用脚本函数后的返回码
  180. if (! (m_IsRuning && m_LuaState))
  181. {
  182. ScriptError(LUA_SCRIPT_STATES_IS_NULL);
  183. return FALSE;
  184. }
  185. {
  186. Lua_GetGlobal(m_LuaState, cFuncName); //在堆栈中加入需要调用的函数名
  187. while (cFormat[i] != '')
  188. {
  189. switch(cFormat[i])
  190. {
  191. case 'n'://输入的数据是double形 NUMBER,Lua来说是Double型
  192. nNumber = va_arg(vlist, double );
  193. Lua_PushNumber(m_LuaState, nNumber);
  194. nArgnum ++;
  195. }
  196. break;
  197. case 'd'://输入的数据为整形
  198. {
  199. nNumber = (double)(va_arg(vlist, int));
  200. Lua_PushNumber(m_LuaState, (double) nNumber);
  201. nArgnum ++;
  202. }
  203. break;
  204. case 's'://字符串型
  205. {
  206. cString = va_arg(vlist, char *);
  207. Lua_PushString(m_LuaState, cString);
  208. nArgnum ++;
  209. }
  210. break;
  211. case 'N'://NULL
  212. {
  213. Lua_PushNil(m_LuaState);
  214. nArgnum ++;
  215. }
  216. break;
  217. case 'f'://输入的是CFun形,即内部函数形
  218. {
  219. CFunc = va_arg(vlist, Lua_CFunction);
  220. Lua_PushCFunction(m_LuaState, CFunc) ;
  221. nArgnum ++;
  222. }
  223. break;
  224. case 'v'://输入的是堆栈中Index为nIndex的数据类型
  225. {
  226. nNumber = va_arg(vlist, int);
  227. int nIndex1 = (int) nNumber;
  228. Lua_PushValue(m_LuaState, nIndex1);
  229. nArgnum ++;
  230. }
  231. break;
  232. case 't'://输入为一Table类型
  233. {
  234. }
  235. break;
  236. case 'p':
  237. {
  238. pPoint = va_arg(vlist, void *);
  239. Lua_PushUserTag(m_LuaState, pPoint,m_UserTag);
  240. nArgnum ++;
  241. }
  242. break;
  243. }
  244. i++;
  245. }
  246. }  
  247.     
  248. nRetcode = Lua_Call(m_LuaState, nArgnum, nResults);
  249. if (nRetcode != 0)
  250. {
  251. ScriptError(LUA_SCRIPT_EXECUTE_ERROR, nRetcode);
  252. return FALSE;
  253. }
  254. return TRUE;
  255. }
  256. //---------------------------------------------------------------------------
  257. // 函数: KLuaScript::CallFunction
  258. // 功能:
  259. // 参数: LPSTR cFuncName
  260. // 参数: int nResults
  261. // 参数: LPSTR cFormat
  262. // 参数: ...
  263. // 返回: BOOL 
  264. //---------------------------------------------------------------------------
  265. BOOL KLuaScript::CallFunction(LPSTR cFuncName, int nResults, LPSTR cFormat, ...)
  266. {
  267. BOOL bResult  = FALSE;
  268. va_list vlist;
  269. va_start(vlist, cFormat);
  270. bResult = CallFunction(cFuncName, nResults, cFormat, vlist);
  271. va_end(vlist);
  272. return bResult;
  273. }
  274. //---------------------------------------------------------------------------
  275. // 函数: KLuaScript::GetValuesFromStack
  276. // 功能: 从堆栈中获得变量
  277. // 参数: char * cFormat
  278. // 参数: ...
  279. // 返回: BOOL 
  280. //---------------------------------------------------------------------------
  281. BOOL KLuaScript::GetValuesFromStack(char * cFormat, ...)
  282. {
  283. va_list vlist;
  284. double* pNumber = NULL;
  285. const char **   pString ;
  286. int * pInt = NULL;
  287. int i = 0;
  288. int nTopIndex = 0;
  289. int nIndex = 0;
  290. int nValueNum = 0;//cFormat的字符长度,表示需要取的参数数量
  291. if (! m_LuaState)
  292. return FALSE;
  293. nTopIndex = Lua_GetTopIndex(m_LuaState);
  294. nValueNum = strlen(cFormat);
  295. if (nTopIndex == 0 || nValueNum == 0)//当堆栈中无数据或不取参数是返回FALSE
  296. return FALSE;
  297. if (nTopIndex < nValueNum)
  298. return FALSE;
  299. nIndex = nTopIndex - nValueNum +1;
  300. {
  301. va_start(vlist, cFormat);     
  302. while (cFormat[i] != '')
  303. {
  304. switch(cFormat[i])
  305. {
  306. case 'n'://返回值为数值形,Number,此时Lua只传递double形的值
  307. {
  308. pNumber = va_arg(vlist, double *);
  309. if (pNumber == NULL)
  310. return FALSE;
  311. if (Lua_IsNumber(m_LuaState, nIndex ))
  312. {
  313. * pNumber = Lua_ValueToNumber(m_LuaState, nIndex ++ );
  314. }
  315. else
  316. {
  317. ScriptError(LUA_SCRIPT_NOT_NUMBER_ERROR);
  318. return FALSE;
  319. }
  320. }
  321. break;
  322. case 'd':
  323. {
  324. pInt = va_arg(vlist, int *);
  325. if (pInt == NULL)
  326. return FALSE;
  327. if ( Lua_IsNumber(m_LuaState, nIndex))
  328. {
  329. * pInt = (int ) Lua_ValueToNumber(m_LuaState, nIndex ++);
  330. }
  331. else
  332. {
  333. ScriptError(LUA_SCRIPT_NOT_NUMBER_ERROR);
  334. return FALSE;
  335. }
  336. }
  337. break;
  338. case 's'://字符串形
  339. {
  340. pString = va_arg(vlist, const char **);
  341. if (pString == NULL)
  342. return FALSE;
  343. if (Lua_IsString(m_LuaState, nIndex))
  344. {
  345. (*pString) = (const char *)Lua_ValueToString(m_LuaState, nIndex++);
  346. }
  347. else
  348. {
  349. ScriptError(LUA_SCRIPT_NOT_STRING_ERROR);
  350. return FALSE;
  351. }
  352. }
  353. break;
  354. }
  355. i ++;
  356. }
  357. va_end(vlist);      /* Reset variable arguments.      */
  358. }
  359. return TRUE;
  360. }
  361. //---------------------------------------------------------------------------
  362. // 函数: KLuaScript::Init
  363. // 功能: 初始化脚本对象,注册系统标准函数库
  364. // 返回: BOOL 
  365. //---------------------------------------------------------------------------
  366. BOOL KLuaScript::Init()
  367. {
  368. if (! m_LuaState)
  369. {
  370. m_LuaState = Lua_Create(0);
  371. if (m_LuaState == NULL)
  372. {
  373. ScriptError(LUA_CREATE_ERROR);
  374. m_IsRuning = FALSE;
  375. return FALSE;
  376. }
  377. m_IsRuning = TRUE;
  378. m_szScriptName[0] = '';
  379. m_UserTag = lua_newtag(m_LuaState) ;
  380. }
  381. RegisterStandardFunctions();
  382. return TRUE;
  383. }
  384. //---------------------------------------------------------------------------
  385. // 函数: KLuaScript::RegisterFunction
  386. // 功能: 注册某内部C函数至脚本中
  387. // 参数: LPSTR FuncName  在脚本中使用的函数名
  388. // 参数: void* Func    实际相应的C函数指针
  389. // 参数: int Args = 0 //与KScript接口相容,无用
  390. // 参数: int Flag = 0 //与KScript接口相容, 无用
  391. // 返回: BOOL 
  392. //---------------------------------------------------------------------------
  393. BOOL KLuaScript::RegisterFunction(LPSTR FuncName , void* Func)
  394. {
  395. if (! m_LuaState)
  396. return FALSE;
  397. Lua_Register(m_LuaState, FuncName, (Lua_CFunction)Func);
  398. return TRUE;
  399. }
  400. //---------------------------------------------------------------------------
  401. // 函数: KLuaScript::Compile
  402. // 功能:
  403. // 参数: char *
  404. // 返回: BOOL 
  405. //---------------------------------------------------------------------------
  406. BOOL KLuaScript::Compile(char *)
  407. {
  408. return TRUE;
  409. }
  410. //---------------------------------------------------------------------------
  411. // 函数: KLuaScript::RegisterFunctions
  412. // 功能: 批量注册Lua的内部C函数,各个函数的信息保存在TLua_Funcs的数据中
  413. // 参数: TLua_Funcs *Funcs 数组的指针
  414. // 参数: int n 函数数量。可以为零,由系统计算得到。
  415. // 返回: BOOL 
  416. //---------------------------------------------------------------------------
  417. BOOL KLuaScript::RegisterFunctions(TLua_Funcs Funcs[], int n)
  418. {
  419. if (! m_LuaState) return FALSE;
  420. if (n == 0) n = sizeof(Funcs) / sizeof(Funcs[0]);
  421. for (int i = 0; i < n; i ++) Lua_Register(m_LuaState, Funcs[i].name, Funcs[i].func);
  422. return TRUE;
  423. }
  424. //---------------------------------------------------------------------------
  425. // 函数: KLuaScript::RegisterStandardFunctions
  426. // 功能: 注册Lua系统标准的函数库
  427. // 返回: void 
  428. //---------------------------------------------------------------------------
  429. void KLuaScript::RegisterStandardFunctions()
  430. {
  431. if (! m_LuaState) return ;
  432. Lua_OpenBaseLib(m_LuaState);//Lua基本库
  433. Lua_OpenIOLib(m_LuaState);//输入输出库
  434. Lua_OpenStrLib(m_LuaState);//字符串处理库
  435. Lua_OpenMathLib(m_LuaState);//数值运算库
  436. //Lua_OpenDBLib(m_LuaState);//调试库
  437. return;
  438. }
  439. //---------------------------------------------------------------------------
  440. // 函数: KLuaScript::ReleaseScript
  441. // 功能: 释放该脚本资源。
  442. // 返回: BOOL 
  443. //---------------------------------------------------------------------------
  444. void KLuaScript::Exit()
  445. {
  446. if (! m_LuaState) return ;
  447. Lua_Release(m_LuaState);
  448. m_LuaState = NULL;
  449. m_IsRuning = FALSE;
  450. }
  451. //---------------------------------------------------------------------------
  452. // 函数: KLuaScript::ScriptError
  453. // 功能:
  454. // 参数: int Error
  455. // 返回: void 
  456. //---------------------------------------------------------------------------
  457. void KLuaScript::ScriptError(int Error)
  458. {
  459. char lszErrMsg[200];
  460. sprintf(lszErrMsg, "ScriptError %d. (%s) n", Error, m_szScriptName);
  461. lua_outerrmsg(lszErrMsg);
  462. return;
  463. }
  464. //---------------------------------------------------------------------------
  465. // 函数: KLuaScript::ScriptError
  466. // 功能:
  467. // 参数: int Error1
  468. // 参数: int Error2
  469. // 返回: void 
  470. //---------------------------------------------------------------------------
  471. void KLuaScript::ScriptError(int Error1 ,int Error2)
  472. {
  473. char lszErrMsg[200];
  474. sprintf(lszErrMsg, "ScriptError %d:[%d] (%s) n", Error1, Error2, m_szScriptName);
  475. lua_outerrmsg(lszErrMsg);
  476. return;
  477. }
  478. //---------------------------------------------------------------------------
  479. // 函数: KLuaScript::SafeCallBegin
  480. // 功能:
  481. // 参数: int * pIndex
  482. // 返回: void 
  483. //---------------------------------------------------------------------------
  484. //---------------------------------------------------------------------------
  485. // SafeCallBegin与SafeCallEnd两函数应搭配使用,以防止在调用Lua的外部函数之后,
  486. //有多余数据在堆栈中未被清除。达到调用前与调用后堆栈的占用大小不变。
  487. //上述情况只需用在调用外部函数时,内部函数不需如此处理。
  488. // Romandou
  489. //---------------------------------------------------------------------------
  490. void KLuaScript::SafeCallBegin(int * pIndex)
  491. {
  492. if (! m_LuaState) return ;
  493. Lua_SafeBegin(m_LuaState, pIndex);
  494. }
  495. //---------------------------------------------------------------------------
  496. // 函数: KLuaScript::SafeCallEnd
  497. // 功能:
  498. // 参数: int nIndex
  499. // 返回: void 
  500. //---------------------------------------------------------------------------
  501. void KLuaScript::SafeCallEnd(int nIndex)
  502. {
  503. if (! m_LuaState) return;
  504. Lua_SafeEnd(m_LuaState, nIndex);
  505. }
  506. //---------------------------------------------------------------------------
  507. // 函数: KLuaScript::StopScript
  508. // 功能: 中止脚本
  509. // 参数: void
  510. // 返回: BOOL 
  511. //---------------------------------------------------------------------------
  512. BOOL KLuaScript::Stop(void)
  513. {
  514. if (! m_IsRuning) return TRUE;
  515. if (! m_LuaState) return FALSE;
  516. m_IsRuning =  FALSE;
  517. return TRUE;
  518. }
  519. //---------------------------------------------------------------------------
  520. // 函数: KLuaScript::ResumeScript
  521. // 功能: 恢复已中止的脚本
  522. // 参数: void
  523. // 返回: BOOL 
  524. //---------------------------------------------------------------------------
  525. BOOL KLuaScript::Resume(void)
  526. {
  527. if ((! m_IsRuning) && (m_LuaState))
  528. {
  529. m_IsRuning = TRUE;
  530. return TRUE;
  531. }
  532. return FALSE;
  533. }
  534. //---------------------------------------------------------------------------
  535. // 函数: KLuaScript::CreateTable
  536. // 功能: 建立一个Lua的Table,在调用该函数并设置Table各个成员之后,必须调用
  537. // SetGlobalName()来给这个Table指定一个名字。
  538. // 返回: DWORD 
  539. //---------------------------------------------------------------------------
  540. DWORD KLuaScript::CreateTable()
  541. {
  542.  int nIndex = 0;
  543. nIndex = Lua_GetTopIndex(m_LuaState) ;
  544. Lua_NewTable(m_LuaState);
  545. if (Lua_GetTopIndex(m_LuaState) != ++nIndex ) 
  546. return -1;
  547. return nIndex;
  548. }
  549. //---------------------------------------------------------------------------
  550. // 函数: KLuaScript::SetGlobalName
  551. // 功能: 设置Lua堆栈顶部的数据一个名字
  552. // 参数: LPSTR szName
  553. // 返回: void 
  554. //---------------------------------------------------------------------------
  555. void KLuaScript::SetGlobalName(LPSTR szName)
  556. {
  557. if (!szName) return ;
  558. Lua_SetGlobal(m_LuaState, szName);
  559. }
  560. //---------------------------------------------------------------------------
  561. // 函数: KLuaScript::ModifyTable
  562. // 功能: 将指定名称的LuaTable置堆栈顶端,并返回顶端Index
  563. // 参数: LPSTR szTableName
  564. // 返回: DWORD 若Lua中不存在该Table则返回-1
  565. //---------------------------------------------------------------------------
  566. DWORD KLuaScript::ModifyTable(LPSTR szTableName) 
  567. {
  568. if (! szTableName[0]) return -1;
  569. int nIndex = Lua_GetTopIndex(m_LuaState);
  570. Lua_GetGlobal(m_LuaState, szTableName);
  571. if (Lua_GetTopIndex(m_LuaState) != ++nIndex) return -1;
  572. return nIndex;
  573. }