声明:本篇博客主要讲解怎样搭建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;
}
运行结果如图所示: