lua5.3与c交互环境

声明:本篇博客主要讲解怎样搭建lua和c交互环境。具体lua和c之间怎么交互调用,可以参考lua5.3程序设计进阶

c调用lua操作时,环境配置如下
1.新建vs c++空工程,如图所示:
在这里插入图片描述
2.下载lua5.3.5的源码并将src目录下的所有文件放入到步骤1中创建的工程里面。如图所示:
在这里插入图片描述
在这里插入图片描述
3.编写一个简单的lua库文件test.lua。代码如下所示:

-- 这是注释
width=2009
height=3009

4.将lua.c以及luac.c等文件中的main函数注释掉,然后新建一个test.c文件。如图所示:
在这里插入图片描述
在这里插入图片描述
5.编写test.c文件。在该文件中启动lua虚拟机加载lua库文件并取出数值进行输出。
代码如下所示:

#include <stdio.h>
#include <stdlib.h>
#include "lua.h"
#include "lauxlib.h"

void error(lua_State* L, const char* fmt, ...)
{
	// 将可变长参数的错误信息填充到标准错误输出流中
	va_list argp;
	va_start(argp, fmt);
	vfprintf(stderr, fmt, argp);
	va_end(argp);
	
	lua_close(L);
	// 由于调用exit时看不到输出结果,所以此处用死循环代替
	//exit(EXIT_FAILURE);
	while (1) {}
}

int getglobint(lua_State* L, const char* var)
{
	int isnum, result;
	// 将全局变量var的值压入栈,并返回该值得类型
	int vt = lua_getglobal(L, var);
	printf("vt:%d\n", vt);

	// 尝试将栈顶元素值转换成整形,失败时抛出错误,成功时就弹出栈并返回
	result = lua_tointegerx(L, -1, &isnum);
	if (!isnum)
	{
		error(L, "'%s' should be a number!\n", var);
	}

	lua_pop(L, -1);
	return result;
}

void load(lua_State* L, const char* filename)
{
	// 加载指定filename文件内容并编译成lua代码块,然后执行该lua代码块
	// 加载或者调用失败时会返回非0错误码,并且lua虚拟机会往栈顶压入错误信息。
	if (luaL_loadfile(L, filename) || lua_pcall(L, 0, 0, 0))
	{
		error(L, "cannot run config.file:%s", lua_tostring(L, -1));
	}

	// 输出lua库文件中全局的变量width和height值
	printf("w=%d, h=%d", getglobint(L, "width"), getglobint(L, "height"));
}

int main(void)
{
	lua_State* L = luaL_newstate();
	// 第二个参数为lua库文件
	load(L, "C:/Users/DELL.DESKTOP-J1LR5AC/Desktop/test.lua");
	
	// 死循环的目的是为了看到输出
	while (1) {};
	return 0;
}

运行结果如图所示:
在这里插入图片描述
lua调用c操作时,环境配置如下
1.新建vs c++空工程,如图所示:
在这里插入图片描述
2.下载lua5.3.5的源码并将src目录下的所有文件放入到步骤1中创建的工程里面。如图所示:
在这里插入图片描述
在这里插入图片描述
3.将lua.c以及luac.c等文件中的main函数注释掉,然后新建一个解释器luaex.c文件。如图所示:
在这里插入图片描述
在这里插入图片描述
4.lua调用c函数有两种方式,分别如下:
4.1.1.编写luaex.c文件。在该文件中通过调用lua_pushcfunction和lua_setglobal函数将c函数l_sin赋值给lua全局变量mysin。然后解释执行包含mysin调用的lua代码(lua代码从终端输入)。
代码如下所示:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"

// 要注册给lua端使用的c端函数
// return:返回值个数
static int l_sin(lua_State* L)
{
	// 获取lua端传递到当前c函数的参数
	double d = lua_tonumber(L, 1);
	// 调用sin函数获取一个正弦值并压入栈中
	lua_pushnumber(L, sin(d));
	// 返回值个数
	return 1;
}

int main(void)
{
	// 创建lua虚拟机对象,使用默认内存分配函数
	lua_State* L = luaL_newstate();
	// 注册所有预定义的标准库(debug,string,table,io等)供lua端使用
	luaL_openlibs(L);
	// 压入c函数到栈顶
	lua_pushcfunction(L, l_sin);
	// 将栈顶的c函数注入到lua的全局变量mysin中
	lua_setglobal(L, "mysin");

	int error = 0;

	// 从标准输入流中获取lua代码
	char buff[256];
	while (fgets(buff, sizeof(buff), stdin) != NULL)
	{
		// 加载lua代码并编译成lua函数代码块,然后调用该函数。成功返回0,否则返回非0并将错误信息压栈
		error = luaL_loadstring(L, buff) || lua_pcall(L,0, 0, 0);
		if (error)
		{
			// 从栈中获取错误信息输出后再弹出
			fprintf(stderr, "%s\n", lua_tostring(L, -1));
			lua_pop(L,1);
		}
	}

	// 没有lua代码时就关闭lua虚拟机
	lua_close(L);
	return 0;
}

运行结果如图所示:
在这里插入图片描述
4.2.1.新建&编写c模块文件lmuslib。
新建如图所示:
在这里插入图片描述代码如下所示:

#include <math.h>
#include "lua.h"
#include "lauxlib.h"

// 要注册给lua端使用的c端函数
// return:返回值个数
static int mus_sin(lua_State* L)
{
	// 获取lua端传递到当前c函数的参数
	double d = luaL_checknumber(L, 1);
	// 调用sin函数获取一个正弦值并压入栈中
	lua_pushnumber(L, sin(d));
	// 返回值个数
	return 1;
}

// 注册数组:格式为{lua函数名称, c函数地址},以{NULL, NULL}结束。
static const struct luaL_Reg muslib[] = {
	{"sin", mus_sin},
	{NULL, NULL}	// 哨兵,也就是结束标识
};

// 定义一个打开函数"luaopen_mus"。可以被"require mus"以静态或者动态库的形式调用
// 也可以在编译lua解释器直接调用。
LUAMOD_API int luaopen_mus(lua_State* L)
{
	// 创建一个新的表,并将muslib中的lua函数名-函数地址填充该表
	luaL_newlib(L, muslib);
	// 返回一个结果,将新创建的表赋值给模块名变量
	return 1;
}

4.2.2.在lualib.h文件中定义模块名宏LUA_MUSNAME以及声明c模块打开函数luaopen_mus。如图所示:
在这里插入图片描述
4.2.3.在linit.c文件中的loadedlibs数组中添加模块名宏LUA_MUSNAME以及c模块打开函数luaopen_mus。如图所示:
在这里插入图片描述
4.2.4.编写luaex.c文件。在该文件中通过调用luaL_openlibs函数将lua函数名sin和c函数mus_sin以表的形式赋值给模块名变量mus。然后解释执行包含mus.sin调用的lua代码(lua代码从终端输入)。
编写代码如下所示:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"

int main(void)
{
	// 创建lua虚拟机对象,使用默认内存分配函数
	lua_State* L = luaL_newstate();
	// 注册所有预定义的标准库(debug,string,table,io等)供lua端使用
	luaL_openlibs(L);
	
	int error = 0;

	// 从标准输入流中获取lua代码
	char buff[256];
	while (fgets(buff, sizeof(buff), stdin) != NULL)
	{
		// 加载lua代码并编译成lua函数代码块,然后调用该函数。成功返回0,否则返回非0并将错误信息压栈
		error = luaL_loadstring(L, buff) || lua_pcall(L,0, 0, 0);
		if (error)
		{
			// 从栈中获取错误信息输出后再弹出
			fprintf(stderr, "%s\n", lua_tostring(L, -1));
			lua_pop(L,1);
		}
	}

	// 没有lua代码时就关闭lua虚拟机
	lua_close(L);
	return 0;
}

运行结果如图所示:
在这里插入图片描述

发布了81 篇原创文章 · 获赞 39 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/zjz520yy/article/details/102685154