如何在C#中实现Lua容器(虚拟文件系统)模块加载器 [英] How to implement a Lua container (virtual file system) module loader in C#

查看:262
本文介绍了如何在C#中实现Lua容器(虚拟文件系统)模块加载器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

听起来有点吓人吗?

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

Some background information, I want to load a tar archive which contains some lua modules into my C# application using LuaInterface. The easiest way would be to extract these files to a temp folder, modify the lua module search path and read them with require as usual. But I do not want to put these scripts somewhere on the file system.

所以我认为应该可以用 #ziplib 加载tar归档文件.很多tar和类似东西的lua实现.但是#zlib已经是项目的一部分.

So I thought it should be possible to load the tar-archive with the #ziplib I know there are a lot of lua implementations for tar and stuff like that. But the #zlib is already part of the project.

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

After successfully loading the file as strings(streams) out of the archive I should be able to pass them into lua.DoString(...) in C# via LuaInterface.

但是,如果模块具有以下行,则仅通过dostring或dofile加载模块不起作用:"module(...,package.seeall)"存在一个错误报告程序,如将参数1传递为nil,但是期望使用字符串.

But simply loading modules by a dostring or dofile does not work if modules have a line like this: "module(..., package.seeall)" There is a error reportet like passing argument 1 a nil, but string expected.

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

The other problem is a module may depend on other modules which are also located in the tar archive.

一种可能的解决方案应该是定义一个自定义加载程序,如此处所述.

One possible solution should be to define a custom loader as described here.

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

My idea is to implement such a loader in C# with the #ziplib and map this loader into the lua stack of my C# application.

你们中有人有类似的任务吗? 有没有可以立即使用的解决方案,已经解决了此类问题?

Does anyone of you had a similar task to this? Are there any ready to use solutions which already address problems like this?

tar文件不是必须具有包格式,而是很好的文件包格式.

The tar file is not must have but a nice to have package format.

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

Is this idea feasible or totally unfeasible?

我已经编写了一些示例类,以从存档中提取lua文件.此方法可用作加载程序并返回lua函数.

I've written some example class to extract the lua files from the archive. This method works as loader and return a lua function.

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_;
}

}

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

I try to register the load method like this in the 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'");

如果我这样尝试,则在调用require时会出现异常:

If I try it this way I'll get an exception while the call to require :

实例方法'load'需要一个非空目标对象"

"instance method 'load' requires a non null target object"

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

I tried to call the load method directly, here I have to use the ":" notation.

lua.DoString("container_module_loader:load('def_sensor')");

如果我这样调用该方法,则会在调试器中遇到一个断点,该断点位于该方法的顶部,因此所有操作均按预期进行.

If I call the method like that I hit a breakpoint in the debugger which is place on top of the method so everything works as expected.

但是,如果我尝试使用:"符号注册方法,则在注册方法时会出现异常:

But If I try to register the method with ":" notation I get an exception while registering the method:

lua.DoString("table.insert(package.loaders, 2, container_module_loader:load)");

"[[字符串" chunk]:1:期望在')'"

"[string "chunk"]:1: function arguments expected near ')'"

推荐答案

中,他们可以正常工作.所有Lua文件都在一个zip文件中,即使使用...,它们也可以工作.他们使用的库是 PhysicsFS .

In LÖVE they have that working. All Lua files are inside one zip file, and they work, even if ... is used. The library they use is PhysicsFS.

看看. /modules/filesystem可能会让您入门.

Have a look at the source. Probably /modules/filesystem will get you started.

这篇关于如何在C#中实现Lua容器(虚拟文件系统)模块加载器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆