Lua与C/C++交互

Posted 两片空白

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Lua与C/C++交互相关的知识,希望对你有一定的参考价值。

前言

        lua是用C语言实现的,提供了一些列接口来实现和C/C++进行数据的交互。可以查阅lua官网的参考手册。

lua_state 虚拟机

        lua_state可以看作是lua的虚拟机,每一个lua虚拟机对应一个lua_state。

        lua_state中包含许多变量,其中就包含lua的私有栈和全局表_G。

struct lua_State

	CommonHeader;//#define CommonHeader	GCObject *next; lu_byte tt; lu_byte marked
	lu_byte status;//虚拟机的错误状态码
	StkId top;//栈顶元素所在位置的下一个位置,也就是栈上第一个空闲的位置
	StkId base;//栈上,当前函数的基址(注意不是函数所在位置)
	global_State* l_G;//全局表,环境章节再说
	CallInfo* ci;//当前函数调用信息
	const Instruction* savedpc;//当前函数的指令位置,指向待取指指令的地址
	StkId stack_last;//栈最后一个位置的下一个位置
	StkId stack;//寄存器数组的起始位置
	CallInfo* end_ci;//函数调用信息数组的最后一个位置的下一个位置
	CallInfo* base_ci;//函数调用信息数组首地址
	int stacksize;//栈的大小
	int size_ci;//函数调用信息数组大小
	unsigned short nCcalls;//内嵌C调用层数
	unsigned short baseCcalls;//唤醒协程时的内嵌C调用层数
	lu_byte hookmask;
	lu_byte allowhook;
	int basehookcount;
	int hookcount;
	lua_Hook hook;
	TValue l_gt;//Global表
	TValue env;//环境表的临时位置
	GCObject* openupval;//open状态的upvalues
	GCObject* gclist;
	struct lua_longjmp* errorJmp;//跳转信息单链表,实现try catch的功能,见函数章节
	ptrdiff_t errfunc;//当前错误处理函数在栈上的索引
;

在C/C++中调用lua函数

C/C++调用全局函数

C函数


#include <stdio.h>
#include "lua.hpp"

int main()

	lua_State* L;//lua私有栈

	L = lua_open();//打开lua,返回lua虚拟机
	luaL_openlibs(L);//加载基础库
	luaL_dofile(L,"test.lua");//执行脚本

	lua_getglobal(L, "add");//将lua全局表中的add压栈
	if (!lua_isfunction(L, -1))//判断是否是函数
	
		printf("function my_pow not found");
        return -1;
	
	lua_pushnumber(L, 2);//压入参数
	lua_pushnumber(L, 8);

	lua_pcall(L, 2, 1, 0);//调用函数,有返回值会压入到栈中
	if (!lua_isnumber(L, -1))//判断返回值
	
		perror("return fail!\\n");
		return -1;
	
	LUA_NUMBER res = lua_tonumber(L, -1);//获得栈顶元素
	printf("res = %f\\n", (float)res);

	lua_close(L);//关闭Lua

	return 0;

lua脚本

function my_pow(x, y)
    return x^y
end

print(my_pow(2, 8))

function add(x, y)
    return x+y
end

C/C++调用全局表中的函数 

C函数

#include <stdio.h>
#include "lua.hpp"

int main()

	lua_State* L;//lua私有栈

	L = lua_open();//打开lua,返回lua虚拟机
	luaL_openlibs(L);//加载基础库

	luaL_dofile(L, "test.lua");//执行脚本

	//将_G 中表名为testTable压栈
	lua_getglobal(L, "testTable");
	if (!lua_istable(L, -1))
	
		printf("table  push fail!\\n");
		return -1;
	
	//将表中对应函数键值压栈
	lua_pushstring(L, "add");
	//会将add键值出栈,将testTable["add"]压栈
	lua_gettable(L, -2);
	if (!lua_isfunction(L, -1))
	
		printf("table function push fail!\\n");
		return -1;
	

	//将参数压栈
	lua_pushnumber(L, 1);
	lua_pushnumber(L, 2);

	//调用函数,将参数函数弹出栈,将返回结果压入栈
	lua_pcall(L, 2, 1, 0);
	LUA_NUMBER res = lua_tonumber(L, -1);
	printf("%f", (float)res);

	lua_close(L);//关闭Lua

	return 0;

lua脚本

testTable = 

function testTable.add(x, y)
    return x + y
end

function testTable.sub(x, y)

    return x -y
end

 在lua中调用C函数

C函数


#include <stdio.h>
#include "lua.hpp"

int printHello(lua_State* L)

	printf("hello world!\\n");
	return 0;


int add(lua_State* L)

	int x = luaL_checknumber(L, -1);//取出栈顶两个元素
	int y = luaL_checknumber(L, -2);
	int res = x + y;
	lua_pushnumber(L, res);
	//返回值为C函数压栈数据数量
	return 1;


void registerFunc(lua_State* L, const char* funcName, lua_CFunction func)

	//lua_register(L, funcName, func);//直接将C函数注册进lua

	lua_pushstring(L, funcName);//将在lua里的c函数名压栈
	lua_pushcclosure(L, func, 0);//将C函数压栈
	lua_settable(L, LUA_GLOBALSINDEX);//使得lua中的全局表中_G[funcName]=func,即在lua中增加函数,实现为C函数


int main()

	lua_State* L;//lua私有栈

	L = lua_open();//打开lua,返回lua虚拟机
	luaL_openlibs(L);//加载基础库

	registerFunc(L, "c_printhello", printHello);//将C函数注册进lua
	registerFunc(L, "c_add", add);

	luaL_dofile(L,"test.lua");//执行脚本

	lua_close(L);//关闭Lua

	return 0;

lua脚本

function test()
    c_printhello()

    local res = c_add(1, 2)
    print(res)
end

--执行函数
test()

 将c函数注册进lua

前提

实现的C函数需要是特定的格式,如下:

例子:

int add(lua_State* L)

	int x = luaL_checknumber(L, -1);//取出栈顶两个元素
	int y = luaL_checknumber(L, -2);
	int res = x + y;
	lua_pushnumber(L, res);
	//返回值为C函数压栈数据数量
	return 1;

两种方式

方式一:

lua5.2被移除了

	lua_pushstring(L, funcName);//将在lua里的c函数名压栈
	lua_pushcclosure(L, func, 0);//将C函数压栈
	lua_settable(L, LUA_GLOBALSINDEX);//使得lua中的全局表中_G[funcName]=func,即在lua中增加函数,实现为C函数

方式二:

lua_register(L, funcName, func);//直接将C函数注册进lua

以上是关于Lua与C/C++交互的主要内容,如果未能解决你的问题,请参考以下文章

Lua与C/C++交互

Lua与C/C++交互

搭建Lua与C/C++交互的环境

搭建Lua与C/C++交互的环境

Lua封装&C++实践——Lua和C/C++的基本交互

Lua封装&C++实践——Lua和C/C++的基本交互