Lua与C/C++交互——C/C++调用Lua脚本
2011-10-07 15:24
731 查看
Lua与C/C++交互——C/C++调用Lua脚本
点此下载代码资源
0.简介
上期介绍了如何在Lua中调用C/C++代码,本期介绍如何在C/C++中调用Lua脚本。有关Lua与C/C++交互的基础知识以及Lua堆栈操作,请见《Lua与C/C++交互——Lua调用C/C++》一文。
本期介绍一个例子,通过Lua来生成一个XML格式的便签。便签格式如下:
我们通过C/C++来输入这些信息,然后让Lua来生成这样一个便签文件。
1. Lua代码
我们通过openNoteFile和closeNoteFile来打开/关闭XML文件。generateNoteXML全局函数接受发送方姓名、接收方姓名、便签内容,生成一个XML便签文件。便签发送时间通过Lua标准库os.time()函数来获取。writeNestedLabel函数根据当前XML的缩进数目来规范XML输出格式。此文件很好理解,不再赘述。
2.C++调用Lua脚本
3.代码解析
3.1.初始化Lua运行时环境
lua_State*所指向的结构中封装了Lua的运行时环境。我们用initLuaEnv这个函数来初始化。lua_open函数用来获取一个新环境,然后我们用luaopen_base打开Lua的基础库,然后用luaL_openlibs打开Lua的io、string、math、table等高级库。
3.2.加载Lua文件
然后我们用luaL_loadfile和lua_pcall来将一个Lua脚本加载到对应的Lua运行时环境中——注意:并不自动执行,只是加载。这两个函数如果返回非0,表示加载失败——你的Lua脚本文件可能未找到或Lua脚本有语法错误……
3.3.加载Lua函数
我们用lua_getglobal函数将Lua脚本中的全局函数、全局变量等入栈,放在栈顶。
3.4.压入Lua函数调用参数
我们用lua_push系列函数来将要调用函数所需参数全部入栈,入栈顺序为Lua函数对应参数从左到右的顺序。
3.5.调用Lua函数
最后用lua_pcall来调用函数。Lua_pcall函数原型如下:
其中,L为此函数执行的Lua环境,nargs为此函数所需的参数个数,nresults为此函数的返回值个数,errfunc为发生错误时错误处理函数在堆栈中的索引。
3.6.获取Lua函数返回值
然后,我们可以通过检测栈顶的位置(从-1开始),来获取返回值。获取返回值后,用lua_pop将栈顶元素出栈——出栈个数为返回值个数。
3.7.释放Lua环境
最后,通过lua_close函数来关闭Lua环境并释放资源。
4.运行结果
我们将GenerateNoteXML.lua脚本和最终的C++生成的GenerateNoteXML.exe放在同一路径下,并运行GenerateNoteXML.exe,在此目录下会生成一个XML文件。如下:
生成的arnozhang_YaFengZhang.xml文件如下:
点此下载代码资源
0.简介
上期介绍了如何在Lua中调用C/C++代码,本期介绍如何在C/C++中调用Lua脚本。有关Lua与C/C++交互的基础知识以及Lua堆栈操作,请见《Lua与C/C++交互——Lua调用C/C++》一文。
本期介绍一个例子,通过Lua来生成一个XML格式的便签。便签格式如下:
<?xml version="1.0" encoding="utf-8" ?> <note> <fromName>发送方姓名</fromName> <toName>接收方姓名</toName> <sendTime>发送时间</sendTime> <msgContent>便签内容</msgContent> </note>
我们通过C/C++来输入这些信息,然后让Lua来生成这样一个便签文件。
1. Lua代码
xmlHead = '<?xml version="1.0" encoding="utf-8" ?>\n' -- Open note file to wriet. function openNoteFile(fileName) return io.open(fileName, "w") end -- Close writed note file. function closeNoteFile(noteFile) noteFile:close() end function writeNestedLabel(ioChanel, label, nestCnt) if nestCnt == 0 then ioChanel:write(label) return end for i = 1, nestCnt do ioChanel:write("\t") end ioChanel:write(label) end function generateNoteXML(fromName, toName, msgContent) local noteFile = openNoteFile(fromName .. "_" .. toName .. ".xml") if not noteFile then return false end noteFile:write(xmlHead) noteFile:write("<note>\n") local currNestCnt = 1 writeNestedLabel(noteFile, "<fromName>", currNestCnt) noteFile:write(fromName) writeNestedLabel(noteFile, "</fromName>\n", 0) writeNestedLabel(noteFile, "<toName>", currNestCnt) noteFile:write(toName) writeNestedLabel(noteFile, "</toName>\n", 0) local sendTime = os.time() writeNestedLabel(noteFile, "<sendTime>", currNestCnt) noteFile:write(sendTime) writeNestedLabel(noteFile, "</sendTime>\n", 0) writeNestedLabel(noteFile, "<msgContent>", currNestCnt) noteFile:write(msgContent) writeNestedLabel(noteFile, "</msgContent>\n", 0) noteFile:write("</note>\n") closeNoteFile(noteFile) return true end
我们通过openNoteFile和closeNoteFile来打开/关闭XML文件。generateNoteXML全局函数接受发送方姓名、接收方姓名、便签内容,生成一个XML便签文件。便签发送时间通过Lua标准库os.time()函数来获取。writeNestedLabel函数根据当前XML的缩进数目来规范XML输出格式。此文件很好理解,不再赘述。
2.C++调用Lua脚本
extern "C" { #include <lua.h> #include <lualib.h> #include <lauxlib.h> #pragma comment(lib, "lua.lib") }; #include <iostream> #include <string> using namespace std; // // 初始化Lua环境. // lua_State* initLuaEnv() { lua_State* luaEnv = lua_open(); luaopen_base(luaEnv); luaL_openlibs(luaEnv); return luaEnv; } // // 加载Lua文件到Lua运行时环境中. // bool loadLuaFile(lua_State* luaEnv, const string& fileName) { int result = luaL_loadfile(luaEnv, fileName.c_str()); if (result) { return false; } result = lua_pcall(luaEnv, 0, 0, 0); return result == 0; } // // 获取全局函数. // lua_CFunction getGlobalProc(lua_State* luaEnv, const string& procName) { lua_getglobal(luaEnv, procName.c_str()); if (!lua_iscfunction(luaEnv, 1)) { return 0; } return lua_tocfunction(luaEnv, 1); } int main() { // 初始化Lua运行时环境. lua_State* luaEnv = initLuaEnv(); if (!luaEnv) { return -1; } // 加载脚本到Lua环境中. if (!loadLuaFile(luaEnv, ".\\GenerateNoteXML.lua")) { cout<<"Load Lua File FAILED!"<<endl; return -1; } // 获取Note信息. string fromName; string toName; string msgContent; cout<<"Enter your name:"<<endl; cin>>fromName; cout<<"\nEnter destination name:"<<endl; cin>>toName; cout<<"\nEnter message content:"<<endl; getline(cin, msgContent); getline(cin, msgContent); // 将要调用的函数和函数调用参数入栈. lua_getglobal(luaEnv, "generateNoteXML"); lua_pushstring(luaEnv, fromName.c_str()); lua_pushstring(luaEnv, toName.c_str()); lua_pushstring(luaEnv, msgContent.c_str()); // 调用Lua函数(3个参数,一个返回值). lua_pcall(luaEnv, 3, 1, 0); // 获取返回值. if (lua_isboolean(luaEnv, -1)) { int success = lua_toboolean(luaEnv, -1); if (success) { cout<<"\nGenerate Note File Successful!"<<endl; } } // 将返回值出栈. lua_pop(luaEnv, 1); // 释放Lua运行时环境. lua_close(luaEnv); system("pause"); return 0; } //:-)
3.代码解析
3.1.初始化Lua运行时环境
lua_State*所指向的结构中封装了Lua的运行时环境。我们用initLuaEnv这个函数来初始化。lua_open函数用来获取一个新环境,然后我们用luaopen_base打开Lua的基础库,然后用luaL_openlibs打开Lua的io、string、math、table等高级库。
3.2.加载Lua文件
然后我们用luaL_loadfile和lua_pcall来将一个Lua脚本加载到对应的Lua运行时环境中——注意:并不自动执行,只是加载。这两个函数如果返回非0,表示加载失败——你的Lua脚本文件可能未找到或Lua脚本有语法错误……
3.3.加载Lua函数
我们用lua_getglobal函数将Lua脚本中的全局函数、全局变量等入栈,放在栈顶。
3.4.压入Lua函数调用参数
我们用lua_push系列函数来将要调用函数所需参数全部入栈,入栈顺序为Lua函数对应参数从左到右的顺序。
3.5.调用Lua函数
最后用lua_pcall来调用函数。Lua_pcall函数原型如下:
int lua_pcall(lua_State* L, int nargs, int nresults, int errfunc);
其中,L为此函数执行的Lua环境,nargs为此函数所需的参数个数,nresults为此函数的返回值个数,errfunc为发生错误时错误处理函数在堆栈中的索引。
3.6.获取Lua函数返回值
然后,我们可以通过检测栈顶的位置(从-1开始),来获取返回值。获取返回值后,用lua_pop将栈顶元素出栈——出栈个数为返回值个数。
3.7.释放Lua环境
最后,通过lua_close函数来关闭Lua环境并释放资源。
4.运行结果
我们将GenerateNoteXML.lua脚本和最终的C++生成的GenerateNoteXML.exe放在同一路径下,并运行GenerateNoteXML.exe,在此目录下会生成一个XML文件。如下:
生成的arnozhang_YaFengZhang.xml文件如下:
相关文章推荐
- LUA与C++交互(在LUA脚本里调用C++函数传参)
- c++与js脚本交互,C++调用JS函数/JS调用C++函数
- (使用lua++)Lua脚本和C++交互(三)
- Lua 与C/C++ 交互系列:通过C调用Lua函数(1)
- Lua 与C/C++ 交互系列: Lua调用C/C++函数(3)
- Lua 与C/C++ 交互系列:通过C++调用Lua函数(2)
- C++调用的LUA脚本中加载其他库的问题
- lua学习系列:c++调用lua脚本的简单示例
- (使用lua++)Lua脚本和C++交互(三)
- C++调用Lua脚本
- Unity3d 调用 Luajit C++ DLL 实现调用 Lua脚本
- c++和MFC 交互通过lua脚本实例
- Lua与C++交互调用(1)
- (使用lua++)Lua脚本和C++交互(四)
- lua同c++的交互之在c++中调用lua代码
- VS2012 C++ 调用LUA脚本
- C++中使用Lua脚本 和lua中调用c的方法
- C++中使用Lua脚本 和lua中调用c的方法
- Lua 与C/C++ 交互系列: Lua调用C/C++函数(1).
- c++与js脚本交互,C++调用JS函数/JS调用C++函数