1.c调用lua的实现原理
lua语言是c语言实现的,而且是非常轻量级的,非常适合内存受限的嵌入式产品
c调用lua,需要在c程序中模拟出lua解释器环境,所以需要调用lua的函数,即生成c程序必定要链接lua库,lua解释器和C是通过一个虚拟栈来交换数据的
栈的大小可以设置,通过查看lua的源码,可以知道这个栈的大小,在luaconf.h的LUAI_MAXSTACK,还可以通过lua_checkstack是调整栈的大小
2.c调用lua的环境搭建(Windows版)
第一步:下载lua源码,官方下载网站http://www.lua.org/ftp/
第二步:根据源码生成lua静态库、lua编译器、lua解释器,实际这些在官网应该都有现成的,但是最好自己实践一下
lua静态库:在VS下新建工程,选择生成静态库、不需要预编译头,包含src的文件,除了lua.c、luac.c
lua编译器:在VS下新建工程,选择生成控制台工程,包含src的文件,除了lua.c
lua解释器:在VS下新建工程,选择生成控制台工程,包含src的文件,除了luac.c
第三步:配置好环境变量(path),指定你lua解释器和编译器的路径
注意:lua主要分5.1版本和5.1以后的版本,lua中的接口发生比较大的变化,还有一些要注意的,特别是在Windows下做lua开发的时候,我列举几个
生成exe时候,链接库的位数和exe位数不同,vs可以配置生成的exe和库是多少位的
生成库的源码和lua解释器不是同一个版本,可能compiler error和running error
总的来说:就是lua解释器和生成lua库的源码最好同一个版本,所以自己用源码生成lua解释器和lua库
3.c调用lua的环境搭建(Linux版)
第一步:下载lua源码,官方下载网站http://www.lua.org/ftp/
第二步:下载libreadline相关支持
sudo apt-get install libreadline5
sudo apt-get install libreadline-gplv2-dev
如果没有这一步,下面安装lua会不成功
第三步:利用Makefile编译
cd lua,进入lua源码目录
make linux,生成lua解释器和编译器、lua库
sudo make install,把lua解释器和编译器、lua库、lua库头文件copy到相应的位置,一般分别是/usr/local目录下的bin、lib、include目录下(实际这一部分和Windows配置环境变量差不多)
4.lua库函数操作交互栈
因为是使用lua库函数,所以需要库路径和头文件路径、指定链接的库名
Linux+gcc:上面这些操作在Linux会省事很多,因为Linux在安装已经放在gcc的搜索路径下了,这部分不用做了,我们只需要指明链接的库名,Linux在生成可执行文件的时候需要类似这样 gcc main.c -o main -llua -lm -ldl,要链接m和dl库,这个是很重要的,因为Linux的lua库用到了这2个库里面的函数
Windows+vs:Windows下我是把lua库放在lua源码目录下里面,头文件就是src下面的部分头文件
下面是利用lua库函数操作栈的实例
#include<stdio.h>
#include<stdlib.h>
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
static void stackDump (lua_State *L)
{
int i = 0;
int top = lua_gettop(L);
for (i = 1; i <= top; i++)
{
int t = lua_type(L, i);
switch (t)
{
case LUA_TSTRING: /* strings */
printf("`%s'", lua_tostring(L, i));
break;
case LUA_TBOOLEAN: /* booleans */
printf(lua_toboolean(L, i) ? "true" : "false");
break;
case LUA_TNUMBER: /* numbers */
printf("%g", lua_tonumber(L, i));
break;
default: /* other values */
printf("%s", lua_typename(L, t));
break;
}
printf(" "); /* put a separator */
}
printf("\n"); /* end the listing */
}
int main(int argc, char** argv)
{
lua_State *L = luaL_newstate(); // 创建Lua虚拟机
luaL_openlibs(L); // 打开Lua状态机"L"中的所有Lua标准库
// 向虚拟栈中压入值
lua_pushboolean(L, 1); // true
lua_pushnumber(L, 10); // 10
lua_pushnil(L); // nil
lua_pushstring(L, "hello"); // "hello"
stackDump(L); // true 10 nil 'hello'
lua_pushvalue(L, -4); // 将索引-4处的值的副本入栈
stackDump(L); // true 10 nil 'hello' true
lua_replace(L, 3); // 将栈顶元素移动到索引3处,并覆盖原先的元素
stackDump(L); // true 10 true 'hello'
lua_settop(L, 6); // 将栈顶设置为索引6处,多出来的新元素被赋值为"nil"
stackDump(L); // true 10 true 'hello' nil nil
lua_remove(L, -3); // 移除索引-3处的元素,其上所有元素下移
stackDump(L); // true 10 true nil nil
lua_settop(L, -5); // 将栈顶设置为索引-5处
stackDump(L); // true
lua_close(L); // 关闭Lua状态机
system("pause");//在Linux下编译,请注释调这行
return 0;
}
5.c调用lua脚本实例
static int multi_math(lua_State *L, int x, int y)
{
int ret = 0;
int add_ret = 0;
int sub_ret = 0;
int mul_ret = 0;
//call lua_add
lua_getglobal(L, "lua_add");//把函数lua_add压入栈中
stackDump(L); //function
lua_pushnumber(L, x); //function 2
lua_pushnumber(L, y); //fucntion 2 1
stackDump(L);
lua_call(L, 2, 1);//指明有2个参数,1个返回值,且把function 2 1弹出栈,并把返回值压入栈
stackDump(L);
add_ret = (int)lua_tonumber(L, -1);
stackDump(L);
printf("add_ret = %d\n", add_ret);
lua_pop(L, 1); //弹出栈顶
stackDump(L);
#if 0
//call local lua_sub will cause running error
lua_getglobal(L, "lua_sub");
lua_pushnumber(L, x);
lua_pushnumber(L, y);
lua_call(L, 2, 1);
sub_ret = (int)lua_tonumber(L, -1);
printf("sub_ret = %d\n", sub_ret);
lua_pop(L, 1);
#endif
//call lua_mul
lua_getglobal(L, "lua_mul");
lua_pushnumber(L, x);
lua_pushnumber(L, y);
lua_call(L, 2, 1);
mul_ret = (int)lua_tonumber(L, -1);
printf("mul_ret = %d\n", mul_ret);
lua_pop(L, 1);
return ret;
}
int main(int argc, char** argv)
{
lua_State *L = luaL_newstate(); // 创建Lua虚拟机
luaL_openlibs(L); // 打开Lua状态机"L"中的所有Lua标准库
printf("call lua ....\n");
if (luaL_dofile(L, "main.lua"))//加载运行main.lua
{
printf("call lua failed!\n");
}
if (multi_math(L, 2, 1))
{
printf("call multi_math failed!\n");
}
lua_close(L); // 关闭Lua状态机
system("pause");
return 0;
}
function lua_add (num1, num2)
return num1 + num2
end
local function lua_sub (num1, num2)
return num1 - num2
end
function lua_mul (num1, num2)
return num1 * num2
end
上面lua库函数就不说明了,有lua源码,不懂可以查看lua源码