« 君子之交淡如水 | 返回首页 | 修正了 jpeg 解码器中的一个 bug »

以自定义方式加载 lua 模块

今天我们的一个小项目开始做内部测试发布前的资源打包。这个项目基本上是用 lua 做开发的。整个开发过程中,我们的代码是直接把 Lua 源代码放在项目的发布目录下的。发布版因为安全或是整洁等种种原因,我们必须给所有的脚本代码打包。

这种事情以前在大话2 里也干过,当时用的 lua 4.0 而且也没多少经验,我们是直接去修改的 lua 的代码,适应我们的打包格式。这次,不想这么干了。希望能够完全不动 lua 官方发布的源代码,来最终完成这项工作。

简单分析了一下,发现实现起来非常简单:

从 Lua 5.1 以后,Lua 有了标准的模块管理库。所以所有的模块加载都是通过 require 来完成。 require 的设计是颇具扩展性的,它会从若干个定义好的 loader 中逐个尝试加载新的模块。系统库中提供了四个 loader ,分别实现已加载模块,Lua 模块,和 C 扩展模块(用了两个 loader 来实现 C 扩展模块的加载)。这些 loader 以 CFunction 的形式放在 require 的环境中的一个 table 里。

如果我们想改变 lua 模块的加载形式,只需要替换或增加一个新的 loader 就可以了。

要做的只需要模仿 loadlib.c 中的 loader_Lua 函数做一个自己的实现,比如在我们的项目中,就允许从自定义格式数据包中,加载一个被加密过的 Lua 代码文件。然后写几行 C 代码,获得 require 的环境(使用 lua_getfenv ),然后取出其中 "loaders" 这个 table ,把新的自定义 loader 插入到 index 2 的地方。

具体的代码就不详述了,仔细阅读一下 ll_require 的实现(在 loadlib.c 中)就很容易明白。我们的整个工作从分析到实现没有超过两个小时,这真是得益于 Lua 良好的设计啊 :D 甚至如果你想从一个网络连接的数据流中加载 Lua 模块,或是通过 http/ftp 协议下载,也是行的通的吧。

Comments

这里有实际可执行的代码(两个函数)
http://www.gamedev.net/topic/517836-solved-lua--how-to-redirect-require-to-load-from-packed-file/
有需要的同学可以看一下

麻烦问下,lua5.1.4版本里,怎样获取这个loaders的table,能给个sample吗。

云风请教
首先,具体怎么替换"loaders"这个table的第二个索引处的值呢?我能读但是不会替换。其次,若用自己程序C++函数来给lua扩展,貌似有很多现成的lua中的方法和变量不能调用(因为没暴露出来),这样会不会比直接改源码多写不少代码呢?

没看明白是什么意思....

lua5.1以后,用什么函数来使用require?

从99年开始就在看你这里的东西。lua也是从2.0开始就开始跟,想不到在你这里看到了lua的东西

哦,看懂了:)

恩,lua的进步啊

基本上是一个简化的Java的ClassLoader的设计

Post a comment

非这个主题相关的留言请到:留言本