lua5.1.4中实现自定义require的loader函数
来源:互联网 发布:淘宝客服聊天记录技巧 编辑:程序博客网 时间:2024/05/01 21:47
刚开始以为只是简单的把自己的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);
- <span style="white-space:pre"> </span>int status =luaL_dofile(L,"Test.lua");
- <span style="white-space:pre"> </span>if (status && !lua_isnil(L, -1))
- {
- const char* error = lua_tostring(L, -1);
- printf("调用脚本出错,错误信息:%s\n",error);
- lua_pop(L, 1);
- }
- lua_close(L);
- lua5.1.4中实现自定义require的loader函数
- lua5.1.4中实现自定义require的loader函数
- lua5.1中实现__gc
- android 自定义 loader实现
- facelet中自定义El函数的实现
- Hive中自定义函数的实现
- Javascript require 的实现
- 自定义指令的require参数
- 自定义Loader的实现---ApiDemos中的LoaderCustom例子分析
- PHP中include与require函数的区别
- php中include、include_once、require、require_once等函数的异同
- Tomcat 中自定义Context Loader
- Lua5.1.4代码分析(二十三)-如何实现Lua代码的热更新
- Lua5.1.4代码分析 如何实现Lua代码的热更新
- Loader的简单实现
- lua5.1.4版本的变量中文支持
- Lua5.3 数学函数
- 自定义函数实现字符串中数据的运算和统计
- 数据库多表连接查询
- linux网络编程之TCP/IP基础(五):分析一帧基于UDP的TFTP协议帧
- sybase IQ(15.2)中的常用函数和存储过程(3)
- zoj 3761 Easy billiards 并查集+dfs
- MySQL 模拟PostgreSQL generate_series 表函数
- lua5.1.4中实现自定义require的loader函数
- TortoiseSVN和VisualSVN-Server的配置使用,外网访问SVN版本库
- 学习Swing做的打飞机小游戏
- java API 学习1 Collections
- Python深入对象的属性
- XCode Debug
- 有关面试经常考的sql语句
- 游标在定义还是打开时读取数据
- 命令行下使用android SDK工具手工开发简单安卓小项目