1. 程式人生 > >從Lua調用C

從Lua調用C

spa table 刪除 返回值 trac 規則 str tracking 類型檢查

從Lua調用C:
方式:C函數從棧中獲取函數參數(第一個參數總是局部棧的索引1),將結果壓入棧中,C函數須要返回結果數量。

每一個函數都有自己的局部私有棧


樣例:
static int l_sin(lua_State *L){
	double d = lua_tonumber(L,1);	//獲取參數,索引為1(私有棧)
	lua_pushnumber(L,sin(d));		//壓入結果
	return 1;						//返回結果的數量
}




註冊函數到Lua:
1、函數的原型: typedef int(*lua_CFunction)(lua_State *L)
在函數返回之前,Lua會自己主動刪除棧中結果之下的內容


2、使用lua_pushcfunction(L,func)
lua_setglobal(L,"mysin")
3、參數類型檢查:將lua_tonumber(L,1)改成luaL_checknumber(L,1)


註冊函數模塊:
luaL_register:這個函數接收一些C函數及其名稱,並將這些函數註冊到一個與模塊同名的table中。
樣例:
C:
static const struct luaL_Reg mylib[] = {
	{"dir",l_dir},
	{NULL,NULL}	//結尾
}
luaL_register(L,"mylib",mylib);


Lua:
require "mylib"
print("mylib.mysin(10)",mylib.mysin(10))

數組操作:


void lua_rawgeti(lua_State* L,int index,int key)
void lua_rawset(L,index,key)


lua_rawgeti(L,t,key)等價於:
lua_pushnumber(L,key)
lua_rawget(L,t)


lua_rawget類似於lua_gettable,差別在於raw能夠繞過元表的index


lua_rawseti(L,t,key)等價於:
lua_pushnumber(L,key)
lua_insert(L,-2) //將‘key‘放到前一個值的以下:由於rawset的規則是key在以下value在棧頂
lua_rawset(L,t)


這兩個函數都是raw操作,比涉及元表的table訪問更快。
演示樣例:
int l_map(lua_State *L){
	int i,n;


	luaL_checktype(L,1,LUA_TTABLE);	//第一個參數必須是一個table
	luaL_checktype(L,2,LUA_TFUNCTION);	//第二個參數必須是一個函數


	n = lua_objlen(L,1);		//獲取table大小
	for(int i=1;i<=n;i++){
		lua_pushvalue(L,2);		//壓入f
		lua_rawgeti(L,1,i);		//壓入t[i]
		lua_call(L,1,1);		//調用f(t[i])
		lua_rawseti(L,1,i);		//t[i] = 結果,***rawseti設置後會清除棧頂的返回值
	}
	
	return 0;
}


從Lua調用C