`
alienchang
  • 浏览: 30825 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Lua C库编程的一些心得

    博客分类:
  • Lua
阅读更多
    在对Lua语言进行C扩展的时候,注意一个最最重要的就是,关键在于Lua那个栈的管理,对参数的接收和返回都是通过那个栈来实现的,所以一定要深刻理解它的栈管理,有些函数如lua_newuserdata会push到栈上,有些函数会pop如luaL_ref,有些函数只取值并不改变栈状态如luaL_checkstring,随时注意栈状态的变化,这个我们可以用lua_gettop函数来观察栈顶变化来估计栈中的内容,lua和C结合在lua中调试很恶心,只能通过printf来估计
    1、关于Lua接口的导出:
    lua是通过在C DLL中export一个luaopen_LUAMODALNAME函数来实现这个导出的,注意那个LUAMODALNAME是你导出的库名,然后需要做的是在这个函数用luaL_openlib 、luasql_set_info或luaL_register来注册打开要导出的函数,这些函数的第三个参数都是一个类似lua table结果的数组,理解了lua栈的工作原理就知道为什么是这个样子的,示例如下:
extern "C" int LURL_API luaopen_lurl(lua_State* L)
{
        const luaL_Reg mylib[] =
{
	{"escape", escape},
	{"deescape", deescape},
	{NULL, NULL}
};
	//lua_register(L, "escape",  escape); //使用lua_register注册函数 
	//lua_register(L, "deescape",  deescape); //使用lua_register注册函数 
	luaL_register(L, "lurl", mylib);
	return 1;
}

     这样在lua中调用require'mylib'时就能打开这个modal了,注意:如果register一个table相当于返回了一个table,然后可以mylib.escape这来调用,而如果register一个函数的话就相当于注册了一个全局函数,直接escape这样调用就行了
LUASQL_API int luaopen_luasql_oci8 (lua_State *L) {
	struct luaL_reg driver[] = {
		{"oci8", create_environment},
		{NULL, NULL},
	};
	create_metatables (L);
	luaL_openlib (L, LUASQL_TABLENAME, driver, 0);
	luasql_set_info (L);
	return 1;
}

    这样在lua中调用require'luasql.oci8'时就能打开这个modal了(注意放到luasql文件夹里才行),然后调用luasql.oci8()时它就会调用create_environment函数了

    2、关于metatable实现:
    使用luasql_createmeta来创建一个metatable如下:
struct luaL_reg statement_methods[] = {
		{"close", stmt_close},
		{"bind_number", stmt_bind_number},
		{"bind_string", stmt_bind_string},
		{"bind_cursor", stmt_bind_cursor},
		{"execute", stmt_execute},
		{NULL, NULL}
	};
luasql_createmeta (L, LUASQL_STATEMENT_OCI8, statement_methods);


    3、关于userdata实现:
    首先lua_newuserdata来新建一个userdata这时它会把这个结果push到栈顶,然后你可以通过 luasql_setmeta来设置它的metatable,或者直接初始化返回,这时结构已经在栈中,return 1通知lua环境你要返回一个返回值就行

    4、关于table的返回:
    有两种方式:1、用lua_createtable来自己创建一个table  2、传入一个空table然后填充然后通过lua_pushvalue复制到栈顶返回(参考luasql中cur_fetch的实现)
填充过程也有两种方式:
    1.)通过void lua_rawseti (lua_State *L, int index, int n);,这种方式是从栈顶淡出value,然后实现t[n] = v 的操作
    2.)通过 lua_rawset 或 lua_settable,这种方式是自定义key的实现,lua先从栈中先弹出key,然后弹出值,实现一个 t[k] = v
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics