c调用lua详解(Windows版+Linux版)

1.c调用lua的实现原理

lua语言是c语言实现的,而且是非常轻量级的,非常适合内存受限的嵌入式产品

c调用lua,需要在c程序中模拟出lua解释器环境,所以需要调用lua的函数,即生成c程序必定要链接lua库,lua解释器和C是通过一个虚拟栈来交换数据的

lua

栈的大小可以设置,通过查看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/

wget -c http://www.lua.org/ftp/lua-5.3.0.tar.gz 
tar zxvf lua-5.3.0.tar.gz 

第二步:下载libreadline相关支持

sudo apt-get install libreadline5
sudo apt-get install libreadline-gplv2-dev

如果没有这一步,下面安装lua会不成功

第三步:修改Makefile支持生成lua.so

官方的Makefile是不支持生产动态库的,所以必须自己动手修改Makefile

1).lua-5.3.0目录下的Makefile修改

TO_LIB= liblua.a 修改为 TO_LIB= liblua.a liblua.so

2).lua-5.3.0/src目录下的Makefile修改

CC= gcc -std=gnu99 修改为 CC= gcc -std=gnu99 -fPIC   (生成地址无关,这个很重要)

在LUA_A=    liblua.a下面增加一行LUA_SO= liblua.so

ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T) 修改为ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T) $(LUA_SO)

在生成lua.a的规则下面增加生成lua.so的规则

$(LUA_SO): $(CORE_O) $(LIB_O)
                    $(CC) -o $@ -shared $? -ldl -lm

第四步:利用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
#include
#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);  // truelua_pushnumber(L, 10); // 10lua_pushnil(L); // nillua_pushstring(L, "hello"); // "hello"stackDump(L); // true  10  nil  'hello'lua_pushvalue(L, -4); // 将索引-4处的值的副本入栈stackDump(L); // true  10  nil  'hello'  truelua_replace(L, 3); // 将栈顶元素移动到索引3处,并覆盖原先的元素stackDump(L); // true  10  true  'hello'lua_settop(L, 6); // 将栈顶设置为索引6处,多出来的新元素被赋值为"nil"stackDump(L); // true  10  true  'hello'  nil  nillua_remove(L, -3); // 移除索引-3处的元素,其上所有元素下移stackDump(L); // true  10  true  nil  nillua_settop(L, -5); // 将栈顶设置为索引-5处stackDump(L); // truelua_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_addlua_getglobal(L, "lua_add");//把函数lua_add压入栈中stackDump(L);				//functionlua_pushnumber(L, x);		//function 2lua_pushnumber(L, y);		//fucntion 2 1stackDump(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_mullua_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
endlocal function lua_sub (num1, num2) return num1 - num2
endfunction lua_mul (num1, num2) return num1 * num2
end

上面lua库函数就不说明了,有lua源码,不懂可以查看lua源码

 

 

 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部