lua作为一门动态语言,可用来当做配置文件和实现经常变化的业务功能,很方便的实现热更新。同时lua作为一门胶水语言,配合强大的C++作逻辑支撑,程序性能高、开发效率快,犹如珠帘合璧,所向无敌。C++与lua的交互主要通过lua的虚拟栈实现,本文不打算深入讲解其中原理,只是简单记录下C++与lua的调用关系。
环境搭建
mac、linux系统:
$ wget http://www.lua.org/ftp/lua-5.2.3.tar.gz
$ tar zxf lua-5.2.3.tar.gz
$ cd lua-5.2.3
$ make posix
$ make posix install
windows系统:略
1.C++调用lua
假如当前文件夹为demo1。先创建一个lua脚本, 路径为:demo1/scripts/test.lua。脚本内容如下:
-- 全局变量
id = 666
title = "this is a test"
array = {r = 2,g = 3,b = 4}
array_1d = {2,5,26,8}
array_2d = {{2,5},{15,18},{25,26,28},{0,5,4}}
-- 无参函数
function ruler_func()
print("[lua]: this is some thing need to tell you!!!");
end
-- 有参函数
function add_func(a,b)
print("[lua]: a("..a..") + b("..b..") ="..a+b.."!");
return a+b;
end
在当前文件夹创建C++文件demo1/demo.cpp,用来测试调用lua脚本。文件内容如下:
/*
* demo.cpp
* demo
*
* Created by Jevstein on 2018/10/16 11:30.
* Copyright @ 2018year Jevstein. All rights reserved.
*
*/
#include <iostream>
#include <string>
using namespace std;
//0.包含lua头文件
extern "C"
{
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
void call_lua_test()
{
//1.创建lua环境
lua_State *L = luaL_newstate(); //lua_open()
if (L == NULL)
{
std::cout << "[C++]: Failed to create Lua State!" << std::endl;
return;
}
//2.加载库
luaL_openlibs(L);//加载终端输出打印信息库,届时可看到lua的print信息
//3.加载lua脚本
const std::string script = "./scripts/test.lua";
int ret = luaL_dofile(L, script.c_str());
if (ret != 0)
{
std::cout << "[C++]: Failed to load lua !" << std::endl;
return;
}
//4.调用脚本内容: 变量、函数等
// 为简化代码,以下可以对其封装,如:
// bool load_file(string str); //加载文件
// string load_string(string str); //读取string变量
// int load_integer(string str); //读取int变量
// double load_double(string str); //读取double变量
// bool load_boolean(string str); //读取bool变量
// bool load_map(const char* name, const int number, string str[], double array_list[], int type = 0); //读取map
// bool load_array(const char* name, int*& array); //读取array
{//4.1.无参函数
std::cout << "[C++]: 1.Get variable !" << std::endl;
lua_getglobal(L, "id");//变量名称
if (lua_isnumber(L, -1))
{
int id = 0;
std::cout << "[C++]: The result is id=" << (int)lua_tointeger(L, -1) << endl;
}
}
{//4.2.无参函数
std::cout << "[C++]: 2.Call ruler_func() !" << std::endl;
lua_getglobal(L, "ruler_func"); //脚本函数名: ruler_func
lua_pcall(L, 0, 0, 0); //用保护模式调用lua函数:入参个数为0、出参个数为0、无自定义错误处理
}
{//4.3.有参函数
int number1 = 100;
int number2 = 200;
printf("[C++]: 3.Call add_func(%d, %d)!\n", number1, number2);
lua_getglobal(L, "add_func"); //脚本函数名: add_func
lua_pushnumber(L, number1); //参数1入参: 100
lua_pushnumber(L, number2); //参数2入参: 200
lua_pcall(L, 2, 1, 0); //函数有两个入参,一个出参,所以函数形式为add(a,b)
//获得返回值: 单回值情况下调用完成后lua会把结果放到栈顶,多返回值时,按照规则存放
if (lua_isnumber(L, -1) != 0)
{
std::cout << "[C++]: The result is :" << lua_tonumber(L, -1) << endl;
}
}
//5.销毁lua环境
lua_close(L);
}
int main()
{
std::cout << "--------- sample: C++ call Lua --------- " << std::endl;
call_lua_test();
std::cout << "--------- the end --------- " << std::endl;
return 0;
}
linux下,使用g++编译:
$ g++ -o demo *.cpp -llua -ldl
执行demo,结果如下:
2.lua调用C++
lua调用C/C++,需要将C/C++编译成动态库。假如当前文件夹为demo2。先创建C++文件, 路径为:demo2/lcpp/MyLuaMath.h和demo2/lcpp/MyLuaMath.cpp。文件内容如下:
C++头文件:
/*
* MyLuaMath.h
* MyLuaMath
*
* Created by Jevstein on 2018/10/17 17:36.
* Copyright @ 2018year Jevstein. All rights reserved.
*
*/
#ifdef __cplusplus
# define EXTERN_C extern "C"
#else//!__cplusplus
# define EXTERN_C
#endif//__cplusplus
#ifdef WIN32
# ifdef MY_EXPORTS
# define MY_REPORT_API EXTERN_C _declspec(dllexport)
# else
# define MY_REPORT_API EXTERN_C _declspec(dllimport)
# endif
# define CALLMODE __cdecl //__stdcall
#else//!WIN32
# define MY_REPORT_API EXTERN_C
# define CALLMODE
#endif//WIN32
/************************************************************************/
/* 函数声明 */
/************************************************************************/
int add_func(lua_State* L);
int sub_func(lua_State* L);
int mul_func(lua_State* L);
int div_func(lua_State* L);
C++实现文件:
/*
* MyLuaMath.cpp
* MyLuaMath
*
* Created by Jevstein on 2018/10/17 17:45.
* Copyright @ 2018year Jevstein. All rights reserved.
*
*/
#include <iostream>
extern "C"
{
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
#include "MyLuaMath.h"
#define MY_EXPORTS
/************************************************************************/
/* 1.函数实现 */
/************************************************************************/
int add_func(lua_State* L)
{
//if (!lua_isnumber(state, 1))
// printf("type invalid!");
int a = lua_tonumber(L, 1);
int b = lua_tonumber(L, 2);
int ret = a + b;
lua_pushnumber(L, ret);
return 1;//1个返回值
}
int sub_func(lua_State* L)
{
int a = lua_tonumber(L, 1);
int b = lua_tonumber(L, 2);
int ret = a - b;
lua_pushnumber(L, ret);
return 1;
}
int mul_func(lua_State* L)
{
int a = lua_tonumber(L, 1);
int b = lua_tonumber(L, 2);
int ret = a * b;
lua_pushnumber(L, ret);
return 1;
}
int div_func(lua_State* L)
{
int a = lua_tonumber(L, 1);
int b = lua_tonumber(L, 2);
int ret = (b == 0) ? 0 : a / b;
lua_pushnumber(L, ret);
return 1;
}
/************************************************************************/
/* 2.函数数组 */
/************************************************************************/
static const struct luaL_Reg funcs__[] =
{
{ "add", add_func },
{ "sub", sub_func },
{ "mul", mul_func },
{ "div", div_func },
{ NULL, NULL }
};
/************************************************************************/
/* 3.导出接口 */
/* [注]函数名luaopen_libmyluamath中的'libmyluamath'必须为库函数名,如:*/
/* libmyluamath.so */
/************************************************************************/
MY_REPORT_API int CALLMODE luaopen_libmyluamath(lua_State* L)
{
//lua5.1之前版本使用如下:
//luaL_openlib(L, "MyMath", funcs__, 0); //或luaL_register(L, "mymath", funcs__);
//lua5.2以上版本使用如下:
lua_getglobal(L, "MyMath");
if (lua_isnil(L, -1))
{
lua_pop(L, 1);
lua_newtable(L);
}
luaL_setfuncs(L, funcs__, 0);
lua_setglobal(L, "MyMath");
return 0;
}
然后创建lua脚本,测试C++的功能。文件路径:demo2/demo.lua,内容如下:
package.cpath = package.cpath .. ";./lcpp/?.so"
require("libmyluamath")
local a = 200
local b = 100
local ret = MyMath.add(a, b)
print("a + b = " ..a .. " + " .. b .. " = "..ret)
local ret = MyMath.sub(a, b)
print("a - b = " ..a .. " - " .. b .. " = "..ret)
local ret = MyMath.mul(a, b)
print("a * b = " ..a .. " * " .. b .. " = "..ret)
local ret = MyMath.div(a, b)
print("a / b = " ..a .. " / " .. b .. " = "..ret)
linux下用g++编译C++动态库:
$ g++ -fPIC -shared -o libmyluamath.so *.cpp -llua -ldl
再用执行脚本:
$ lua demo.lua
结果如下:
|
请发表评论