Lua学习笔记——C语言与Lua的交互

Lua与C的交互

C代码不可以直接与Lua代码交互,中间是通过Lua引擎实现的(C代码要调用Lua需要链上Lua引擎库 gcc lua.c -llua50)
gcc lua.c -llua5.1     //链上Lua50引擎库,之后lua.c就可以  如果提示没有lua50库,就使用 sudo apt-get install liblua5.1-0-dev 安装lua引擎库

Lua堆栈一般最多可以容纳20个参数

第一部分:Lua调用C函数
STEP1 执行lua脚本
lua.c内容如下

	#include
	#include
	#include
	
	int main()
	{
		//1.创建lua state(Lua解析器实例,类似于java虚拟机)     //将来与Lua交互必须使用创建的解析器实例,  //每个线程可以创建多个解析器实例
		lua_State* luaInst = lua_open()
		
		//2.初始化Lua解析器实例对象
		luaL_openlibs(luaInst)
		
		//3.执行Lua
		luaL_dofile(luaInst,"1.lua")   //执行当前目录下的lua脚本
		
		return 0;
	}

	当加入main函数,可以实现与系统自带解析器一样的功能
		#include
		#include
		#include	
		int main(int argc,char*argv[])
		{
			lua_State* luaInst = lua_open()
			luaL_openlibs(luaInst)
			luaL_dofile(luaInst,argv[1])   //执行传入参数指定的Lua脚本    
			return 0;
		}

		利用gcc lua.c -llua5.1  生成a.out
		./a.out  1.lua     与lua 1.lua执行结果一样


---------------------------------------------------------------------------
STEP2 lua调用C函数
lua.c内容如下
	#include
	#include
	#include	
	
	//1. 定义接口函数,接口函数有固定的格式,int(*func_type)(lua_State*)
	//2.将接口函数注册到lua解析器中
	//3.执行lua脚本,在脚本中执行对应的函数
	void callbylua()
	{
		printf("this function is called by lua ");
	}
	
	int c1(lua_State* L)
	{
		callbylua();
		return 0;
	}
	
	int main()
	{
		lua_State* luaInst = lua_open();
		luaL_openlibs(luaInst,"c1",c1) ;    //注册C函数到Lua
		luaL_dofile(luaInst,"./1.lua");   //执行传入参数指定的Lua脚本    
		return 0;
	}
	
1.lua内容如下
	print("this is 1.lua")
	c1()


---------------------------------------------------------------------------
STEP3 lua调用C函数:带有参数
lua.c内容如下
	#include
	#include
	#include		
	void cprint(int a,int b,char* c)
	{
		printf("%d,%d,%s\n",a,b,c);
	}
	int c2(lua_State* L)        //需要从lua栈中获取三个参数
	{
		int a = lua_tonumber(L,1);     //根据lua解析器栈的索引值来获取参数
		int b = lua_tonumber(L,2);
		char* c = lua_tostring(L,3);
		cprint(a,b,c);
		return 0;
	}
	int main()
	{
		lua_State* luaInst = lua_open();
		luaL_openLibs(luainst);
		lua_register(luaInst,"cprint",c2);
		luaL_dofile(luaInst,"./1.lua");
	}
1.lua内容如下
	print("this is 1.lua")
	c2(10,20,“helloC”)				//lua解析器中有一个栈,	栈中的元素从左往右,依次是栈底,到栈顶;索引栈分为	索引与 尾索引(负数)			

	
	
---------------------------------------------------------------------------
STEP4 lua调用C函数:带有参数和返回值
lua.c内容如下
	#include
	#include
	#include		
	int cadd(int x,int y)
	{
		return x+y;
	}
	int c4(lua_State* L)
	{
		int x = lua_tonumber(L,1);
		int y = lua_tonumber(L,2);
		int s = cadd(x,y);
		lua_pushnumber(L,s);       //返回值
		return 1;                //返回有多少个返回值
	}
	
	int main()
	{
		lua_State* luaInst = lua_open();
		luaL_openLibs(luainst);
		lua_register(luaInst,"cadd",c4)
		luaL_dofile(luaInst,"./1.lua")
	}
1.lua内容如下
	print("this is 1.lua")
	ret = cadd(10,20)				//lua解析器中有一个栈,	栈中的元素从左往右,依次是栈底,到栈顶;索引栈分为	索引与 尾索引(负数)			
	print("cadd ret =",ret)


---------------------------------------------------------------------------
STEP5 lua调用C函数:带有参数和返回值
lua.c内容如下
	#include
	#include
	#include		
	void cswap(int* x,int* y)
	{
		return x+y;
	}
	int c5(lua_State* L)
	{
		int x = lua_tonumber(L,1);
		int y = lua_tonumber(L,2);
		cswap(x,y);
		lua_pushnumber(L,x);       //返回值
		lua_pushnumber(L,y);       //返回值
		return 2;                //返回有多少个返回值
	}
	
	int main()
	{
		lua_State* luaInst = lua_open();
		luaL_openLibs(luainst);
		lua_register(luaInst,"cswap",c5)
		luaL_dofile(luaInst,"./1.lua")
	}
1.lua内容如下
	print("this is 1.lua")
	a,b = cswap(10,20)				//lua解析器中有一个栈,	栈中的元素从左往右,依次是栈底,到栈顶;索引栈分为	索引与 尾索引(负数)			
	print("cadd ret =",a,b)
	
	
	
	
第二部分:C调用Lua函数
#include 
#include 
#include 

// 1. 调用一个没有参数,没有返回值的函数
	// call lua function: foo
	int main1(int argc, char* argv[])
	{
		// 创建一个Lua解析器环境实例,类似Java的虚拟机
		lua_State* luaInst = lua_open();
		// 初始化Lua解析器环境实例对象
		luaL_openlibs(luaInst);

		// 执行Lua
		luaL_dofile(luaInst, "2.lua");


		// 在调用lua_call函数去调用lua函数之前,需要把lua的函数放入栈(foo是一个Lua中的函数变量)
		lua_getglobal(luaInst, "foo"); 

		// 调用lua的一个函数,有没有指定哪个函数????   第二个参数是所调用函数的参数个数,第三个参数是返回值的个数
		lua_call(luaInst, 0, 0);         //没有指定具体的函数,解析器的栈决定     ;该函数调用完毕之后,解析器栈内部会清空

		return 0;
	}

----2.lua的内容	
	function foo()
		print("foo in lua is called")
	end

	


// 2. 调用一个有参数的函数
int main2(int argc, char* argv[])
{
    // 创建一个Lua解析器环境实例,类似Java的虚拟机
    lua_State* luaInst = lua_open();
    // 初始化Lua解析器环境实例对象
    luaL_openlibs(luaInst);

    // 执行Lua
    luaL_dofile(luaInst, "2.lua");


    // 在调用lua_call函数去调用lua函数之前,需要把lua的函数放入栈
    lua_getglobal(luaInst, "luaprint"); // foo其实是一个函数类型变量
    lua_pushnumber(luaInst, 100);
    lua_pushstring(luaInst, "hello");

    // 调用lua的foo函数,有没有指定哪个函数????
    lua_call(luaInst, 2, 0); 

    return 0;
}
----2.lua的内容	
	function luaprint(x, y)
		print("lua get arg:", x, y)
	end

// 3. 调用一个有返回值的函数
	int main(int argc, char* argv[])
	{
		// 创建一个Lua解析器环境实例,类似Java的虚拟机
		lua_State* luaInst = lua_open();
		// 初始化Lua解析器环境实例对象
		luaL_openlibs(luaInst);

		// 执行Lua
		luaL_dofile(luaInst, "2.lua");


		// 在调用lua_call函数去调用lua函数之前,需要把lua的函数放入栈
		lua_getglobal(luaInst, "luaadd"); // foo其实是一个函数类型变量
		lua_pushnumber(luaInst, 100);
		lua_pushnumber(luaInst, 200);

		// 调用lua的foo函数,有没有指定哪个函数????
		lua_call(luaInst, 2, 1);

		int result = lua_tonumber(luaInst, -1);
		printf("luaadd result is %d\n", result);

		lua_pop(luaInst, 1); // POP 一个元素,保证栈被清空

		return 0;
	}

----3.lua的内容	
	function luaadd(x, t)
		return x+y;
	end



第三部分:Lua与C/C++纯数据交互

原理:Lua解析器实际是将Lua脚本中的语句翻译为C代码保存在Lua解析器中,因而可以使用C直接编辑Lua解析器中的数据结构
lua.c内容如下:
	//向lua解析器中写入变量a并赋值
	#include 
	#include 
	#include 

	// 放一个普通的全局变量
	int main1(int argc, char* argv[])
	{
		// 创建一个Lua解析器环境实例,类似Java的虚拟机
		lua_State* luaInst = lua_open();
		// 初始化Lua解析器环境实例对象
		luaL_openlibs(luaInst);

		// push一个value到栈
		lua_pushnumber(luaInst, 100);     //为lua_setglobal做铺垫,因为此时栈为空

		// 放一个a变量
		lua_setglobal(luaInst, "a");     //lua_setglobal函数执行过程为:从栈顶获取一个值赋值给“a”,然后将栈顶元素弹出来;将a压入堆栈

		// 执行Lua
		luaL_dofile(luaInst, "3.lua");
		return 0;
	}
//3.lua中的内容为
	print(a)       //虽然3.lua没有a变量,但是C语言已经将a加入了栈中



	// 放一个表
	int main2(int argc, char* argv[])
	{
		// 创建一个Lua解析器环境实例,类似Java的虚拟机
		lua_State* luaInst = lua_open();
		// 初始化Lua解析器环境实例对象
		luaL_openlibs(luaInst);

		// 阶段1:先创建全局表b
		// push一个value到栈
		lua_newtable(luaInst);
		// 放一个b变量
		lua_setglobal(luaInst, "b");

		// 阶段2:给b来一个成员,叫name                                 
		lua_getglobal(luaInst, "b"); // 将b表,放入栈                   |__________|
		lua_pushstring(luaInst, "tom");                                 |__________|目前栈顶是“tom”  		 -1位置       key是"name"  value是"tom"
		lua_setfield(luaInst, -2, "name"); // b.name = "tom"            |__________|栈顶下面有一个table	 	-2位置
										|__________|
		// 执行Lua
		luaL_dofile(luaInst, "3.lua");
		return 0;
	}

	int main3()
	{
		// 创建一个Lua解析器环境实例,类似Java的虚拟机
		lua_State* luaInst = lua_open();
		// 初始化Lua解析器环境实例对象
		luaL_openlibs(luaInst);
														//这类函数需要考虑栈的具体状态,需要查看各个函数弹栈与否,画图分析						
		lua_newtable(luaInst);
		lua_pushstring(luaInst, "tom");
		lua_setfield(luaInst, -2, "name");
		lua_setglobal(luaInst, "b");							//简化/优化上面的代码,setfield会弹出tom的值,但是表还在

		luaL_dofile(luaInst, "3.lua");
	}

	int main()
	{
		lua_State* luaInst = lua_open();
		luaL_openlibs(luaInst);

		lua_newtable(luaInst);
		lua_pushnumber(luaInst, 1);
		lua_pushstring(luaInst, "hello lua");
		
		lua_settable(luaInst, 1);							//相当于t[k] = v   操作   ,(由于setfield下标是字符串,settable下标是数字)
		
		lua_setglobal(luaInst, "b");

		luaL_dofile(luaInst, "3.lua");
	}
3.lua内容如下:	
print(a)
print(b.name)
print(b[1])


	
	
	
	

你可能感兴趣的:(Lua,lua)