将Brotli编译成DLL .NET可以参考

gt6*_*07a 10 c# python compression python.net brotli

所以我想利用Brotli,但我不熟悉Python和C++.

我知道有人将其编译成Windows .exe.但是如何将其包装到DLL或.NET应用程序可以引用的内容中呢?我知道有IronPython,我是否只是将所有源文件引入IronPython项目并编写调用Brotli API的.NET适配器并公开它们?但实际上,我甚至不确定Brotli API是Python还是C++.

看着tools/bro.cc,它看起来像"进入"方法在定义encode.cdecode.cBrotliCompress(),BrotliDecompressBuffer(),BrotliDecompressStream()的方法.所以我想可以从C++类编译DLL.

Sim*_*ier 13

为了避免使用Python,我在https://github.com/smourier/brotli中分享了原始的brotli源代码,并创建了一个可以与.NET一起使用的Windows DLL版本.我添加了一个目录,其中包含一个带有两个项目的"WinBrotli"Visual Studio 2015解决方案:

  • WinBrotli:一个Windows DLL(x86和x64),包含原始未更改的C/C++ brotli代码.
  • Brotli:用C#编写的Windows控制台应用程序(任何Cpu),包含WinBrotli的P/Invoke互操作代码.

要重用Winbrotli DLL,只需复制WinBrotli.x64.dll和WinBrotli.x86.dll(您可以在WinBrotli/binaries文件夹中找到已构建的发行版本),而不是 .NET应用程序,并将BrotliCompression.cs文件合并到C#中项目(或将其移植到VB或其他语言,如果C#不是您最喜欢的语言).互操作代码将自动选择与当前进程的位数(X86或X64)相对应的正确DLL.

完成后,使用它非常简单(输入和输出可以是文件路径或标准.NET Streams):

        // compress
        BrotliCompression.Compress(input, output);

        // decompress
        BrotliCompression.Decompress(input, output);
Run Code Online (Sandbox Code Playgroud)

要创建WinBrotli,这就是我所做的(对于其他想要使用其他Visual Studio版本的人)

  • 创建了一个标准的DLL项目,删除了预编译的头文件
  • 包括所有编码器和解码器原始brotli C/C++文件(从未更改任何内容,因此我们可以在需要时更新原始文件)
  • 配置项目以删除对MSVCRT的依赖(因此我们不需要部署其他DLL)
  • 禁用4146警告(否则我们无法编译)
  • 添加了一个非常标准的dllmain.cpp文件,没有什么特别之处
  • 添加了一个WinBrotli.cpp文件,该文件将brotli压缩和解压缩代码暴露给外部Windows世界(具有非常薄的适配层,因此在.NET中更容易互操作)
  • 添加了一个导出4个函数的WinBrotli.def文件


Evk*_*Evk 5

我将通过从.NET代码调用python本机库来展示一种方法.你需要什么:

  1. 你需要intall python 2.7(希望很明显)
  2. 你需要从源代码编译brotli.希望这很容易.首先为Python 2.7安装Microsoft Visual C++编译器.然后克隆brotli存储库git clone https://github.com/google/brotli.git并使用编译python setup.py build_ext.完成后,在build\lib.win32-2.7目录中你会找到brotli.pyd文件.这是python c ++模块 - 我们稍后会需要它.

  3. 您需要下载pythonnet二进制文件或从源代码编译它.我们在这里使用pythonnet的原因,而不是Iron Python,因为Iron Python不支持本机(C\C++)python模块,这就是我们在这里需要的.所以,要从源代码编译,git clone https://github.com/pythonnet/pythonnet.git然后通过编译来克隆python setup.py build.结果你会得到Python.Runtime.dll(在build\lib.win32-2.7目录中),这是我们需要的.

完成所有操作后,创建控制台项目,引用Python.Runtime.dll,然后:

public static void Main()
{            
    PythonEngine.Initialize();            
    var gs = PythonEngine.AcquireLock();
    try {                
        // import brotli module
        dynamic brotli = PythonEngine.ImportModule(@"brotli");
        // this is a string we will compress
        string original = "XXXXXXXXXXYYYYYYYYYY";
        // compress and interpret as byte array. This array you can save to file for example
        var compressed = (byte[]) brotli.compress(original);                
        // little trick to pass byte array as python string
        dynamic base64Encoded = new PyString(Convert.ToBase64String(compressed));
        // decompress and interpret as string
        var decompressed = (string) brotli.decompress(base64Encoded.decode("base64"));
        // works
        Debug.Assert(decompressed == original);
    }
    finally {
        PythonEngine.ReleaseLock(gs);
        PythonEngine.Shutdown();
    }            
    Console.ReadKey();
}
Run Code Online (Sandbox Code Playgroud)

然后构建它并将你在上面的brotli.pyc与.exe文件放在同一目录中.在完成所有操作之后,您将能够从.NET代码进行压缩和解压缩,如上所示.


Jin*_*Xie 4

您可以使用 Brotli.NET,它提供完整的流支持。

  1. github: https: //github.com/XieJJ99/brotli.net/
  2. Nuget: https: //www.nuget.org/packages/Brotli.NET/

要将流压缩为 brotli 数据:

   public Byte[] Encode(Byte[] input)
   {
       Byte[] output = null;
       using (System.IO.MemoryStream msInput = new System.IO.MemoryStream(input))
       using (System.IO.MemoryStream msOutput = new System.IO.MemoryStream())
       using (BrotliStream bs = new BrotliStream(msOutput, System.IO.Compression.CompressionMode.Compress))
       {
           bs.SetQuality(11);
           bs.SetWindow(22);
           msInput.CopyTo(bs);
           bs.Close();
           output = msOutput.ToArray();
           return output;
       }
   }
Run Code Online (Sandbox Code Playgroud)

要解压缩 brotli 流:

   public Byte[] Decode(Byte[] input)
   {
       using (System.IO.MemoryStream msInput = new System.IO.MemoryStream(input))
       using (BrotliStream bs = new BrotliStream(msInput, System.IO.Compression.CompressionMode.Decompress))
       using (System.IO.MemoryStream msOutput = new System.IO.MemoryStream())
       {
           bs.CopyTo(msOutput);
           msOutput.Seek(0, System.IO.SeekOrigin.Begin);
           output = msOutput.ToArray();
           return output;
       }

   }
Run Code Online (Sandbox Code Playgroud)

要在 Web 应用程序中支持动态压缩,请在 Global.asax.cs 中添加如下代码:

    protected void Application_PostAcquireRequestState(object sender, EventArgs e)
    {
                       var app = Context.ApplicationInstance;
            String acceptEncodings = app.Request.Headers.Get("Accept-Encoding");

            if (!String.IsNullOrEmpty(acceptEncodings))
            {
                System.IO.Stream baseStream = app.Response.Filter;
                acceptEncodings = acceptEncodings.ToLower();

                if (acceptEncodings.Contains("br") || acceptEncodings.Contains("brotli"))
                {
                    app.Response.Filter = new Brotli.BrotliStream(baseStream, System.IO.Compression.CompressionMode.Compress);
                    app.Response.AppendHeader("Content-Encoding", "br");
                }
                else
                if (acceptEncodings.Contains("deflate"))
                {
                    app.Response.Filter = new System.IO.Compression.DeflateStream(baseStream, System.IO.Compression.CompressionMode.Compress);
                    app.Response.AppendHeader("Content-Encoding", "deflate");
                }
                else if (acceptEncodings.Contains("gzip"))
                {
                    app.Response.Filter = new System.IO.Compression.GZipStream(baseStream, System.IO.Compression.CompressionMode.Compress);
                    app.Response.AppendHeader("Content-Encoding", "gzip");
                }

            }
       }        
Run Code Online (Sandbox Code Playgroud)