分享

lua调用C++写的DLL实现“热更新”

 kiki的号 2017-04-04

原创作品,转载请注明来源是CSDN:http://blog.csdn.net/relar/article/details/38084689

开发游戏服务器往往有“热更新”的需求,就是在不停止服务程序的情况下,对服务程序进行升级。这里采用lua脚本桥接C++的模式。程序主框架用C++,程序的业务逻辑也是C++(具体的是C++写的DLL),这两者之间用LUA脚本语言进行桥接。当程序运行时,只要改变LUA脚本,即可以选择使用不同的DLL,以实现业务逻辑的升级更新。

上演示代码,代码分为三部分,第一部分是主程序:

  1. //本例演示了lua调用DLL  
  2.   
  3. #include "stdafx.h"  
  4. #include <stdio.h>  
  5. #include <string.h>  
  6. #include <malloc.h>  
  7. #include <conio.h>  
  8. #include "include\lua.hpp"  
  9.   
  10.   
  11.   
  12. int _tmain(int argc, _TCHAR* argv[])  
  13. {  
  14.   
  15.     int global_var1 = 0;  
  16.     printf("这个程序演示Lua调用C++的Dll:\n");  
  17.     lua_State *pLuaState = luaL_newstate(); //也可以用lua_open();  
  18.     luaL_openlibs(pLuaState);  
  19.   
  20.     if (luaL_dofile(pLuaState, "main2.lua"))// 加载脚本文件  
  21.     {  
  22.         printf("dofile error.\n");  
  23.     }  
  24.     _getch();  
  25.     if (luaL_dofile(pLuaState, "main2.lua"))// 第二次加载脚本文件  
  26.     {  
  27.         printf("dofile error.\n");  
  28.     }  
  29.     _getch();  
  30.     lua_close(pLuaState);  
  31.   
  32.     return 0;  
  33. }  

第二部分是DLL,我的工程名称是Func1,编译出来的自然是Func1.dll

  1. #include "my.h"  
  2.   
  3. int GameLogic1(lua_State *L)  
  4. {  
  5.     int n = lua_gettop(L);  
  6.     double sum = 0;  
  7.     int i;  
  8.   
  9.     for (i = 1; i <= n; i++)  
  10.     {  
  11.   
  12.         sum += lua_tonumber(L, i);  
  13.     }  
  14.   
  15.     lua_pushnumber(L, sum / n);  
  16.   
  17.     lua_pushnumber(L, sum);  
  18.   
  19.     return 2;  
  20. }  
  21. const struct luaL_Reg Func1lib[] = {  
  22.         { "GameLogic1", GameLogic1 },  
  23.         { NULL, NULL }  
  24. };  
  25.   
  26.   
  27. int luaopen_Func1lib(lua_State* L)  
  28. {  
  29.     luaL_openlib(L, "Func1lib", Func1lib, 0);  
  30.     return 1;  
  31. }  

其中my.h的代码如下:

  1. #include "include\lua.hpp"  
  2.   
  3. #pragma comment(lib, "lua5.1.lib")  
  4.   
  5. #if defined(_WIN32)  
  6. extern "C" _declspec(dllexport)  int luaopen_Func1lib(lua_State* L);  
  7.   
  8. #else  
  9. extern "C" int luaopen_Func1lib(lua_State* L);  
  10. #endif  

注意,上面extern "C"这几句曾让我浪费了不少时间。因为DLL是用C++写的,而LUA是用C写的,所以一定要用extern "C"语句。

下面是LUA脚本:

[python] view plain copy 在CODE上查看代码片派生到我的代码片
  1. local testlib = package.loadlib("E://Func1.dll""luaopen_Func1lib")  
  2. print(testlib)--, "Can not open testlib.")  
  3. if(testlib)then  
  4.     testlib();  --调用DLL中抛出函数  
  5.     a,b=Func1lib.GameLogic1(6,6)  
  6.     print("average:",a,"sum:",b);  
  7.     a,b=Func1lib.GameLogic2(3,6)  
  8.     print("average:",a,"sum:",b);  
  9. else  
  10.     print("Error")  
  11. end  

这个脚本也让我浪费了很长时间,它有两个陷阱,第一,它一定要写DLL的绝对路径,第二,这个脚本在LUA命令行中无法运行,只有在C++程序中被调用。不注意这两点会让你疯掉。

另外我按照Func1.dll又写一个Func2.dll,内容稍有不同(这里就不必上代码了哈),演示的时候主程序执行了第一次加载脚本后会等待用户输入任意键,此时可以把脚本改为使用Func2.dll,再输入任意键让程序继续运行,业务逻辑就改了。

还有人是把业务逻辑以纯LUA实现,但是LUA自身功能有限,它生来就是用来调用或被C/C++调用的。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多