如何在C#中实现Lua容器(虚拟文件系统)模块加载器

gra*_*ans 5 c# lua module tar luainterface

听起来有点可怕不是吗?

一些背景信息,我想使用LuaInterface将包含一些lua模块的tar存档加载到我的C#应用​​程序中.最简单的方法是将这些文件解压缩到临时文件夹,修改lua模块搜索路径并像往常一样用require读取它们.但我不想把这些脚本放在文件系统的某个地方.

所以我认为应该可以使用#ziplib加载tar-archive 我知道有很多用于tar的lua实现和类似的东西.但#zlib已经是该项目的一部分.

成功将文件作为字符串(流)从存档中加载后,我应该能够通过LuaInterface将它们传递给C#中的lua.DoString(...).

但是,如果模块有这样的行,那么简单地通过dostring或dofile加载模块就不起作用了:"module(...,package.seeall)"有一个错误报告,比如将参数1传递给nil,但是字符串是预期的.

另一个问题是模块可能依赖于也位于tar存档中的其他模块.

一种可能的解决方案应该是定义这里描述的自定义加载器.

我的想法是使用#ziplib在C#中实现这样的加载器,并将此加载器映射到我的C#应用​​程序的lua堆栈中.

你们中有谁有类似的任务吗?有没有现成的解决方案已经解决了这样的问题?

tar文件不是必须的,但包装格式很好.

这个想法是可行还是完全不可行?

我写了一些示例类来从存档中提取lua文件.此方法用作加载器并返回lua函数.

namespace LuaInterfaceTest
{
 class LuaTarModuleLoader
 {
    private LuaTarModuleLoader() { }
    ~LuaTarModuleLoader()
    {
        in_stream_.Close();
    }
    public LuaTarModuleLoader(Stream in_stream,Lua lua )
    {
        in_stream_ = in_stream;
        lua_ = lua;
    }

    public LuaFunction load(string modulename, out string error_message)
    {
        string lua_chunk = "test=hello";
        string filename = modulename + ".lua";
        error_message = "Unable to locate the file";
        in_stream_.Position = 0; // rewind
        Stream gzipStream = new BZip2InputStream(in_stream_);
        TarInputStream tar = new TarInputStream(gzipStream);
        TarEntry tarEntry;
        LuaFunction func = null;
        while ((tarEntry = tar.GetNextEntry()) != null)
        {
            if (tarEntry.IsDirectory)
            {
                continue;
            }
            if (filename == tarEntry.Name)
            {
                MemoryStream out_stream = new MemoryStream();
                tar.CopyEntryContents(out_stream);
                out_stream.Position = 0; // rewind
                StreamReader stream_reader = new StreamReader(out_stream);
                lua_chunk = stream_reader.ReadToEnd();
                func = lua_.LoadString(lua_chunk, filename);
                string dum = func.ToString();
                error_message = "No Error!";
                break;
            }
        }
        return func;
    }
    private Stream in_stream_;
    private Lua lua_;
}
Run Code Online (Sandbox Code Playgroud)

}

我尝试在LuaInterface中注册这样的加载方法

        Lua lua = new Lua();
        GC.Collect();
        Stream inStream = File.OpenRead("c:\\tmp\\lua_scripts.tar.bz2");
        LuaTarModuleLoader tar_loader = new LuaTarModuleLoader(inStream, lua);
        lua.DoString("require 'CLRPackage'");
        lua.DoString("import \"ICSharpCode.SharpZipLib.dll\"");
        lua.DoString("import \"System\"");
        lua["container_module_loader"] = tar_loader;
        lua.DoString("table.insert(package.loaders, 2, container_module_loader.load)");
        lua.DoString("require 'def_sensor'");
Run Code Online (Sandbox Code Playgroud)

如果我这样尝试,我会在调用require时遇到异常:

"实例方法'加载'需要非空目标对象"

我试着直接调用load方法,这里我必须使用":"符号.

lua.DoString("container_module_loader:load('def_sensor')");
Run Code Online (Sandbox Code Playgroud)

如果我调用这样的方法,我在调试器中点了一个断点,它位于方法之上,所以一切都按预期工作.

但是如果我尝试用":"符号注册方法,我在注册方法时会遇到异常:

lua.DoString("table.insert(package.loaders, 2, container_module_loader:load)");
Run Code Online (Sandbox Code Playgroud)

"[string"chunk"]:1:预期在')'附近的函数参数

kik*_*ito 3

L\xc3\x96VE中,他们可以做到这一点。所有 Lua 文件都位于一个 zip 文件内,即使...使用,它们也能正常工作。他们使用的库是PhysicsFS

\n\n

看看源码。也许 /modules/filesystem 会让你开始。

\n