《C++的十万个为什么》 [50]一半是性能,一半是灵活——C++和Lua混合编程(怎么在C++代码中调用Lua脚本的函数?)
《C++的十万个为什么》 [50]一半是性能,一半是灵活——C++和Lua混合编程(如何在C++代码中调用Lua脚本的函数?)
http://chenlq.net/dev/cpp-why/50-half-performance-half-of-the-flexible-c-and-lua-hybrid-programming-how-lua-script-function-call-in-the-c-code.html
[50]一半是性能,一半是灵活——C++和Lua混合编程(如何在C++代码中调用Lua脚本的函数?)
Q:
在[49]一半是性能,一半是灵活——C++和Lua混合编程(如何在C++中执行Lua脚本?)中,我们介绍了如何在C++程序化中执行Lua脚本,然而很多时候,我们并不需要执行整个脚本,而是只要执行脚本中的某个函数完成某个功能就可以了,那么,如何在C++代码中执行Lua脚本中的函数呢?
A:
在C++代码中执行Lua脚本的函数,跟直接执行Lua脚本非常相似,只是因为函数的执行涉及到函数名的查找,参数以及返回值的传递,所以多了一些将参数和返回值出栈入栈的操作,而这些,Lua都提供了相应的函数(lua_getglobal()获取函数,lua_pushnumber()参数入栈,lua_call()调用函数)来完成,使用起来也非常方便。
我们来看一个具体的例子,在贪吃蛇游戏中,我们需要判断当前贪吃蛇到达的位置是否还在场景之内(isinscene()函数)。如果我们把这个判断逻辑以如下的形式固化在程序当中:
bool isinscene(int x,int y)
{
if(x > 0 && x < 100
&& y > 0 && y < 100 )
{
return true;
}
else
{
return false;
}
}
那么,整个程序就失去了灵活性,这个程序只能将场景限制在(0,0,100,100)范围之内,如果我们的需求发生了变化,场景变大或者是变小,我们不得不修改源代码,然后重新编译并发布给客户。
而如果是使用在C++代码中调用Lua函数来实现这种容易变化的逻辑,那么,整个程序将灵活得多。
要做到这一点,首先在C++代码中搭建起调用Lua函数的框架:
// 引入Lua需要的头文件
// 如果是C语言代码,extern "C"可以省略
extern "C"
{
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
};
#include <iostream>
// 判断x,y是否在场均内
bool inscene(lua_State* L,int x,int y)
{
bool isin = false; // 初始值,未在场景内
if(nullptr != L)
{
// 根据函数名获得Lua中的函数
lua_getglobal(L, "inscene");
lua_pushnumber(L, x); // 参数一入栈
lua_pushnumber(L, y); // 参数二入栈
// 调用Lua中的inscene函数,
// 这里的2,1表示两个输入参数,一个返回值
lua_call(L, 2, 1);
// 获得bool类型的返回值
isin = lua_toboolean(L, -1);
lua_pop(L, 1);// 将返回值出栈,恢复栈中的元素
}
return isin;
}
// C++程序执行Lua脚本
int main()
{
// Lua解释器指针
lua_State* L = nullptr;
// 创建Lua解释器
L = luaL_newstate();
if(nullptr != L)
{
luaL_openlibs(L);// 打开Lua库
// 执行Lua脚本snake.lua
luaL_dofile(L, "snake.lua");
int x = 10;
int y = 40;
// 调用Lua脚本中的函数
bool isin = inscene(L, x, y);
// 输出结果
http://chenlq.net/dev/cpp-why/50-half-performance-half-of-the-flexible-c-and-lua-hybrid-programming-how-lua-script-function-call-in-the-c-code.html
[50]一半是性能,一半是灵活——C++和Lua混合编程(如何在C++代码中调用Lua脚本的函数?)
Q:
在[49]一半是性能,一半是灵活——C++和Lua混合编程(如何在C++中执行Lua脚本?)中,我们介绍了如何在C++程序化中执行Lua脚本,然而很多时候,我们并不需要执行整个脚本,而是只要执行脚本中的某个函数完成某个功能就可以了,那么,如何在C++代码中执行Lua脚本中的函数呢?
A:
在C++代码中执行Lua脚本的函数,跟直接执行Lua脚本非常相似,只是因为函数的执行涉及到函数名的查找,参数以及返回值的传递,所以多了一些将参数和返回值出栈入栈的操作,而这些,Lua都提供了相应的函数(lua_getglobal()获取函数,lua_pushnumber()参数入栈,lua_call()调用函数)来完成,使用起来也非常方便。
我们来看一个具体的例子,在贪吃蛇游戏中,我们需要判断当前贪吃蛇到达的位置是否还在场景之内(isinscene()函数)。如果我们把这个判断逻辑以如下的形式固化在程序当中:
bool isinscene(int x,int y)
{
if(x > 0 && x < 100
&& y > 0 && y < 100 )
{
return true;
}
else
{
return false;
}
}
那么,整个程序就失去了灵活性,这个程序只能将场景限制在(0,0,100,100)范围之内,如果我们的需求发生了变化,场景变大或者是变小,我们不得不修改源代码,然后重新编译并发布给客户。
而如果是使用在C++代码中调用Lua函数来实现这种容易变化的逻辑,那么,整个程序将灵活得多。
要做到这一点,首先在C++代码中搭建起调用Lua函数的框架:
// 引入Lua需要的头文件
// 如果是C语言代码,extern "C"可以省略
extern "C"
{
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
};
#include <iostream>
// 判断x,y是否在场均内
bool inscene(lua_State* L,int x,int y)
{
bool isin = false; // 初始值,未在场景内
if(nullptr != L)
{
// 根据函数名获得Lua中的函数
lua_getglobal(L, "inscene");
lua_pushnumber(L, x); // 参数一入栈
lua_pushnumber(L, y); // 参数二入栈
// 调用Lua中的inscene函数,
// 这里的2,1表示两个输入参数,一个返回值
lua_call(L, 2, 1);
// 获得bool类型的返回值
isin = lua_toboolean(L, -1);
lua_pop(L, 1);// 将返回值出栈,恢复栈中的元素
}
return isin;
}
// C++程序执行Lua脚本
int main()
{
// Lua解释器指针
lua_State* L = nullptr;
// 创建Lua解释器
L = luaL_newstate();
if(nullptr != L)
{
luaL_openlibs(L);// 打开Lua库
// 执行Lua脚本snake.lua
luaL_dofile(L, "snake.lua");
int x = 10;
int y = 40;
// 调用Lua脚本中的函数
bool isin = inscene(L, x, y);
// 输出结果