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/

第二步:下载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源码

猜你喜欢

转载自blog.csdn.net/follow_blast/article/details/81735632
今日推荐