zoukankan      html  css  js  c++  java
  • 函数环境lua5.1.4中实现自定义require的loader函数

    废话就不多说了,开始。。。

        刚开始认为只是简单的把自己的C函数,替换到package.loaders[2](索引2是lua的文件加载器)里头就OK了,实际上也是这样的,但是这样的价值就是文件搜索啊,一堆一堆的判断啊都要自己做,因为这些lua本身已实现了,所以肯定直接拿来用之。但问题来了,发明直接简单的package.loaders[2]=myloadfunc是失败的。会抛出这个错误:

        luaL_error(L, LUA_QL("package.%s") " must be a string", pname);

        好吧,我碰到个没碰到的问题:环境,之前这个货色观点的始终不清楚的,我也没想去马上去了解。于是Google,能搜到的唯一有效的货色就是云风博客上的那篇文章,里头说要先获取函数的环境,然后再设置给自己的函数。。。。。。。完整不懂,说的太简单,毕竟人家完整不考虑我们这些入门级选手。去找API,发明有个getfenv,然后为了便利直接用dostring来设置看看,结果失败。打印后发明,不管获取什么的环境都是一样的表。无奈之下去了解环境的观点,大概弄明白了,于是发明根据那个观点,似乎怎么都获取不到,毕竟你要在函数里头才能获取到环境,或者返回一个闭包才能获取到函数里头的环境。但是最好还是想到云风那个做法,于是想试试CAPI是否能获取到环境表。谜底是肯定的,CAPI就可以获取到package.loaders[2]的环境表。但是因为CAPI操作不熟练,弄了半天都没弄好,其实是弄错了设置table的方法,把自己的CFunction作为键放到loaders里头去了。找了半天,再去看看以前弄的操作,终究找到原因。改好后又涌现重复加载文件的错误,调试了半天发明是自己写错文件名,活该的初级错误。最终终究一切正常,泪流满面。有了自定义的require,加上之前实现的lua_Reader,完整可以解析加密过的lua文件。

        鉴于网上关于lua的资料其实太少,放出来大家分享一下。

        luajit2.0.1通用

    typedef int (*manual_load_file_func)(lua_State* L, const char* filename);
    typedef int (*readable_func)(const char* filename);
        每日一道理
    悲观的人,先被自己打败,然后才被生活打败;乐观的人,先战胜自己,然后才战胜生活。悲观的人,所受的痛苦有限,前途也有限;乐观的人,所受的磨难无量,前途也无量。在悲观的人眼里,原来可能的事也能变成不可能;在乐观的人眼里,原来不可能的事也能变成可能。悲观只能产生平庸,乐观才能造就卓绝。从卓绝的人那里,我们不难发明乐观的精神;从平庸的人那里,我们很容易找到阴郁的影子。
    static manual_load_file_func manul_load_file = NULL;
    static readable_func readablefunc = NULL;
    
    static void loaderror(lua_State *L, const char *filename)
    {
    	luaL_error(L, "error loading module " LUA_QS " from file " LUA_QS ":\n\t%s",
    		lua_tostring(L, 1), filename, lua_tostring(L, -1));
    }
    
    static const char *pushnexttemplate(lua_State *L, const char *path)
    {
    	const char *l;
    	while (*path == *LUA_PATHSEP) path++;  /* skip separators */
    	if (*path == '\0') return NULL;  /* no more templates */
    	l = strchr(path, *LUA_PATHSEP);  /* find next separator */
    	if (l == NULL) l = path + strlen(path);
    	lua_pushlstring(L, path, (size_t)(l - path));  /* template */
    	return l;
    }
    
    static const char *searchpath (lua_State *L, const char *name,
    							   const char *path, const char *sep,
    							   const char *dirsep)
    {
    	luaL_Buffer msg;  /* to build error message */
    	luaL_buffinit(L, &msg);
    	if (*sep != '\0')  /* non-empty separator? */
    		name = luaL_gsub(L, name, sep, dirsep);  /* replace it by 'dirsep' */
    	while ((path = pushnexttemplate(L, path)) != NULL) {
    		const char *filename = luaL_gsub(L, lua_tostring(L, -1),
    			LUA_PATH_MARK, name);
    		lua_remove(L, -2);  /* remove path template */
    		if (readablefunc && readablefunc(filename))  /* does file exist and is readable? */
    			return filename;  /* return that file name */
    		lua_pushfstring(L, "\n\tno file " LUA_QS, filename);
    		lua_remove(L, -2);  /* remove file name */
    		luaL_addvalue(&msg);  /* concatenate error msg. entry */
    	}
    	luaL_pushresult(&msg);  /* create error message */
    	return NULL;  /* not found */
    }
    
    static const char *findfile(lua_State *L, const char *name,
    							const char *pname)
    {
    	const char *path;
    	lua_getfield(L, LUA_ENVIRONINDEX, pname);
    	path = lua_tostring(L, -1);
    	if (path == NULL)
    		luaL_error(L, LUA_QL("package.%s") " must be a string", pname);
    	return searchpath(L, name, path, ".", LUA_DIRSEP);
    }
    
    static int lua_file_from_manual_func(lua_State *L)
    {
    	const char *filename;
    	const char *name = luaL_checkstring(L, 1);
    	filename = findfile(L, name, "path");
    	if (filename == NULL) return 1;  /* library not found in this path */
    	if (manul_load_file && manul_load_file(L, filename) != 0)
    		loaderror(L, filename);
    	return 1;  /* library loaded successfully */
    }
    
    void InitManualFunction(lua_State *L, manual_load_file_func loadfilefunc, readable_func readalbefunc_in )
    {
    	manul_load_file = loadfilefunc;
    	readablefunc = readalbefunc_in;
    
    	lua_getglobal(L,"package");
    	lua_getfield(L,-1,"loaders");//package.loaders
    	lua_pushnumber(L, 2);
    	lua_gettable(L, -2);//package.loaders[2]
    	lua_pushnumber(L,2);//先把索引压栈,呆会用来设置C函数到这个索引位置
    	lua_pushcfunction(L,lua_file_from_manual_func);//压入自己的C函数
    	lua_getfenv(L,-3);//获取旧函数的环境表
    	int ret=lua_setfenv(L,-2);//设置到新函数
    	lua_settable(L,-4);//替换旧函数
    	lua_pop(L,3);//清理堆栈
    }

        使用:

    lua_State* L = luaL_newstate();
    	luaL_openlibs(L);
    
    	InitManualFunction(L, my_load_file, readable);

        int status =luaL_dofile(L,"Test.lua");

        if (status && !lua_isnil(L, -1)) { const char* error = lua_tostring(L, -1); printf("调用脚本出错,错误信息:%s\n",error); lua_pop(L, 1); } lua_close(L);

    文章结束给大家分享下程序员的一些笑话语录: Google事件并不像国内主流媒体普遍误导的那样,它仅仅是中国Z府和美国公司、中国文化和美国文化甚至中国人和美国人之间的关系,是民族主义和帝国主义之间的关系;更重要的是,它就是Z府和公司之间的关系,是权力管制和市场自由之间的关系。从这个意义上说,过度管制下的受害者,主要是国内的企业。Google可以抽身而去,国内的企业只能祈望特区。www.ishuo.cn

  • 相关阅读:
    jupyterlab数据处理
    系统监测模块
    登录验证码的实现
    编码格式检测chardet模块
    图像处理pillow模块
    内存数据的读取
    力扣(LeetCode)728. 自除数
    力扣(LeetCode)709. 转换成小写字母
    Java 层序创建和遍历二叉树
    力扣(LeetCode) 849. 到最近的人的最大距离
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3074107.html
Copyright © 2011-2022 走看看