自己尝试实现了一个lua_Reader
2013-05-03 23:13
423 查看
为什么要自己实现呢,因为脚本这东西总要加密,lua似乎没有直接从内存读取脚本这东西,似乎dostring可以,不过因为听说效率较低所以pass,而且dostring也不能读取编译后的文件。
其实纯C的函数指针和C++等高级语言的抽象接口差不多,不过灵活度还是要高很多。现在发现面向对象有些东西的确是太死板了,以前觉得模板这东西很强大,现在发现这个不过是来弥补先天的不足,那还不如C的函数指针来得直接方面和明了。
不过习惯了面向对象,要转到函数式编程还有点绕不开,去看了关于lua自己的lua_Reader的实现,分别是dostring和dofile的实现,大概只是这个东西只是解析相应的资源,最终给lua_load用来加载block。如果只是简单的字符串就简单了,直接传进去就好了,dostring就是这么干的,而dofile就复杂很多,仔细分析,最需要的区别还是对于有无BOM和编译后的lua文件的解析,对于一般的需求,那个判断BOM我就不弄了,但是还是要判断是否编译了。
最初自己卡在一个地方,后来发现原来是lua5.1编译好的文件lua5.2根本不认,好吧,手头没有5.2的编译器,只好拿源码去编个,然后就搞定了。总结来说,最大的区别就是文件头是不是LUA_SIGNATURE。lua_load会先读取第一个字符,发现是编译文件就用编译文件策略,然后进行读后面的字符。
另一个其实不太明白的地方是关于buffer的大小,看起来dostring似乎并没有考虑这个问题,可能也并不需要处理这个问题,但是dofile里面却是用了LUAL_BUFFERSIZE(512)这个值,每次只读512个字节,虽然不知道为什么要这样不过我还是模仿了他。
贴一下代码,这里的从文件读取其实可以换成从内存,反正只是buffer的不同而已。而且我也自己去判断是否是编译文件了。
想要吐槽的是,lua_load之前都还好,之后简直不知道该怎么阅读,实在太绕了,果然水平还不够啊。我找了半天,最终没有找到lua_Reader被调用的地方,后来想到其实可以单步调试进去看流程,原来面向过程还要这点好处,就是过程非常明了。。。不过C风格的命名真的很蛋疼!怎么剩怎么来
其实纯C的函数指针和C++等高级语言的抽象接口差不多,不过灵活度还是要高很多。现在发现面向对象有些东西的确是太死板了,以前觉得模板这东西很强大,现在发现这个不过是来弥补先天的不足,那还不如C的函数指针来得直接方面和明了。
不过习惯了面向对象,要转到函数式编程还有点绕不开,去看了关于lua自己的lua_Reader的实现,分别是dostring和dofile的实现,大概只是这个东西只是解析相应的资源,最终给lua_load用来加载block。如果只是简单的字符串就简单了,直接传进去就好了,dostring就是这么干的,而dofile就复杂很多,仔细分析,最需要的区别还是对于有无BOM和编译后的lua文件的解析,对于一般的需求,那个判断BOM我就不弄了,但是还是要判断是否编译了。
最初自己卡在一个地方,后来发现原来是lua5.1编译好的文件lua5.2根本不认,好吧,手头没有5.2的编译器,只好拿源码去编个,然后就搞定了。总结来说,最大的区别就是文件头是不是LUA_SIGNATURE。lua_load会先读取第一个字符,发现是编译文件就用编译文件策略,然后进行读后面的字符。
另一个其实不太明白的地方是关于buffer的大小,看起来dostring似乎并没有考虑这个问题,可能也并不需要处理这个问题,但是dofile里面却是用了LUAL_BUFFERSIZE(512)这个值,每次只读512个字节,虽然不知道为什么要这样不过我还是模仿了他。
贴一下代码,这里的从文件读取其实可以换成从内存,反正只是buffer的不同而已。而且我也自己去判断是否是编译文件了。
struct LoadFile { bool hasHead; int n; char* buffer; char* bufferToRead; }; static const char *getFile(lua_State *L, void *ud, size_t *size) { LoadFile *lf = (LoadFile *)ud; (void)L; /* not used */ if(lf->hasHead) { *size = 1; lf->hasHead = false; return LUA_SIGNATURE; } if(lf->n==0)return NULL; if (lf->n > LUAL_BUFFERSIZE) { *size = LUAL_BUFFERSIZE; lf->bufferToRead = lf->buffer; lf->buffer += LUAL_BUFFERSIZE; lf->n -= LUAL_BUFFERSIZE; } else { *size = lf->n; lf->bufferToRead = lf->buffer; lf->n = 0; } return lf->bufferToRead; } int LoadLuaFile(lua_State* L, const char* fileName, bool isLuac = false) { int ret = 0; lua_pushfstring(L, "@%s", fileName); HANDLE hFile = NULL; hFile = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL); DWORD size = GetFileSize(hFile, NULL); BYTE buffer[40960]; DWORD flag; ReadFile(hFile,buffer,size,&flag,0); CloseHandle(hFile); LoadFile file; file.n = 0; if (isLuac) { file.hasHead = true; file.n = size-1; file.buffer = (char*)(buffer+1); } else { file.hasHead = false; file.n = size; file.buffer = (char*)(buffer); } ret = lua_load(L, getFile, &file, lua_tostring(L, -1), NULL); return ret; }
想要吐槽的是,lua_load之前都还好,之后简直不知道该怎么阅读,实在太绕了,果然水平还不够啊。我找了半天,最终没有找到lua_Reader被调用的地方,后来想到其实可以单步调试进去看流程,原来面向过程还要这点好处,就是过程非常明了。。。不过C风格的命名真的很蛋疼!怎么剩怎么来
相关文章推荐
- Lua自己实现载入一个模块
- 实现自己的LUA绑定器-一个模板编程挑战
- Lua自己实现载入一个模块
- 尝试自己写一个工具类实现UGUI的按钮功能
- 装饰模式——自己实现一个BufferedReader
- 实现自己的LUA绑定器-一个模板编程挑战
- 【装饰设计模式】写一个MyBufferedReader实现自己的ReadLine方法、增强BufferedReader的ReaderLine()
- 自己实现的一个寻径算法的框架,具体算法采用动态库模式,可以非常方便灵活地尝试多种寻径算法
- Lua自己实现深度克隆一个值
- 自己实现的一个寻径算法的框架,具体算法采用动态库模式,可以非常方便灵活地尝试多种寻径算法
- 创建一个数组, 实现函数init()初始化数组、 实现reverse()函数完成数组元素的逆置,实现empty()清空数组。要求:自己设计函数的参数,返回值。
- ASP.NET MVC:如何实现一个自己的ModelBinder?
- EventBus猜想 ----手把手带你自己实现一个EventBus
- 自己实现一个PullToZoomListView放大回弹效果,PullToZoomView源码解析
- 2010年10月20日 [原]自己实现的一个MessageBox()
- 1. 实现一个函数,打印乘法口诀表,口诀表的行数和列数自己指定, 输入9,输出9*9口诀表,输出12,输出12*12的乘法口诀表。
- 菜鸟自己实现一个多线程操作对象中的同一个数据
- 自己用 Netty 实现一个简单的 RPC
- 自己实现的一个简单的HttpEngine库
- 一个自己编写的象棋程序,可实现走棋谱(如炮二平五),工程完成度%96,跟大家分享一下,下一步要做残局,欢迎交流