【问题标题】:How to embed a ruby gem into a C# project and require it from an embedded IronRuby script?如何将 ruby​​ gem 嵌入到 C# 项目中并从嵌入式 IronRuby 脚本中要求它?
【发布时间】:2012-02-17 18:49:11
【问题描述】:

我有一个 C# 项目,其中嵌入了 IronRuby 程序。该项目(包括我的 ruby​​ 脚本)在 Visual Studio 2010 中编译为 .exe 文件以进行分发。我正在使用与此类似的模式来引导 IronRuby 脚本:http://pastebin.com/NKes1cyc(Jimmy Schementi 在此处详细介绍:http://blog.jimmy.schementi.com/2009/12/ironruby-rubyconf-2009-part-35.html)。

我的问题:我想在我的 C# 程序集中嵌入一个 gem (json_pure) 并从 ruby​​ 脚本中调用它。

我找到的一些资源:

  1. 在 JRuby 中,您可以轻松地将 gem 打包到 jar 文件中,然后在运行时简单地请求该 jar 文件 - http://blog.nicksieger.com/articles/2009/01/10/jruby-1-1-6-gems-in-a-jar

  2. irpack 工具(http://github.com/kumaryu/irpack)能够在嵌入 ruby​​ 标准库的同时将 Ruby 编译为 .exe(我认为它会动态创建和编译 C# 项目)。但看起来它只嵌入了预构建的 IronRuby .dll,而不是 ruby​​ .rb 文件。如果我能弄清楚如何将 Ruby 源文件编译成 .dll,那么这个工具使用的方法就可以了。

如何将 IronRuby gem 嵌入到 C# 程序集中(或将 IronRuby gem 编译为 .dll)?

编辑:

IronRuby In Action

第 472 页(“使用外部库”)解释了如何在嵌入式 ruby​​ 文件中要求标准 ruby​​ 库。它涉及将文件夹添加到运行时搜索路径集合,如下所示(为简洁明了而编辑):

ScriptEngine engine = IronRuby.Ruby.CreateEngine();
var searchPaths = engine.GetSearchPaths().Concat(new[] 
{
    "C:\\Program Files (x86)\\IronRuby 1.1\\Lib\\ruby\\1.9.1",
    "C:\\Program Files (x86)\\IronRuby 1.1\\Lib\\ironruby"
});
engine.SetSearchPaths(searchPaths)

此方法假定主机已安装 IronRuby,但我想将 ruby​​ 文件(来自 gem)嵌入到程序集中,以便在没有预先安装 IronRuby 的情况下运行它。

编辑 2(进一步研究):

阅读上面提到的 irpack 工具的源代码,我注意到 Kumaryu 是通过 System.IO.Packaging.Package 类将资源嵌入到最终程序集中,然后将包传递给 msbuild 的调用(参见@ 987654325@)。也许对将文件打包成可执行文件的进一步研究会导致解决方案。我看到的问题是 gem require 其他 ruby​​ 文件中的 ruby​​ 文件...可以在程序集包中的 ruby​​ 文件require 同一包中的其他 ruby​​ 文件吗?

编辑 3:

我还没有得到任何进一步的答案,但我很想听听任何人的反馈,即使它只是一个链接或关于在哪里查看的建议。我是 msbuild 的新手,文档非常丰富。对“msbuild embed zip package”的初始网络搜索未发现任何相关内容。

【问题讨论】:

标签: c# .net msbuild .net-assembly ironruby


【解决方案1】:

Require is a method 可以像任何其他 ruby​​ 方法一样被覆盖。我认为这就是原始 ruby​​ gems 包的工作方式,gems 会简单地覆盖require

如果您可以通过某种方式将 gem 打包到 .exe 中,则可以覆盖 require 以从程序集中加载。

【讨论】:

  • 一些 Ruby gem 包含多个 Ruby 文件目录。我宁愿有一个打包机制来保持该结构完好无损(否则,我必须编辑 gem 中的每个 .rb 文件;这不适用于像 active_record 或 json_pure 这样的大型 gem)。
  • 自动打包会更好,但编写一个脚本将所有 .rb 文件打包成一个 .cs 文件作为 Map 并不难
  • 好主意! ...但是,如果 Ruby 文件以字符串文字的形式存在,那么压缩它们会更加困难。 AFAIK,MSBuild 允许您压缩嵌入式资源。对于更大(和多个)宝石,这可能变得很重要。
  • 我不确定对已编译的 .cs 文件进行了哪些压缩。更糟糕的是,您的字符串文字可能是 .zip 压缩的 .rb 文件的 base64 编码。
  • 接受这个答案,因为它是迄今为止唯一一个提供完整(尽管很困难)解决方案的答案。
【解决方案2】:

我正在与 https://stackoverflow.com/users/2086/mcintyre321 合作,使用我的打包代码 (https://github.com/rifraf/IronRubyAppPackager#readme) 将他的库打包到 C#/IronRuby 中。

在 vendorize 步骤中需要一些修复,这些修复与嵌入而不是加载 RubyGems 的更高版本的 Ruby 相关,但正在取得进展。

他的代码需要“json”,我有一个技巧可以强制它使用 Ruby 实现而不是 C-linkage .so 文件。这应该意味着它可以与 IronRuby 一起使用。将报告回来,或者随时与我联系并告知您要运行的来源。

【讨论】:

  • 等待你的回报 - 赏金即将到期:)
【解决方案3】:

试试这个https://github.com/rifraf/IronRubyAppPackager#readme(或等待我报告它是否适用于我尝试嵌入的库)

报告:

我走的流程是……

  1. https://github.com/rifraf 分叉和子模块所有项目(IronRubyEmbeddedApps、IronRubyAppPackager、Serfs 和 Vendorize),并将它们全部添加到 VS 解决方案中。我将所有项目更新为 .NET4 并让它们相互引用,而不是包含的 .net2 程序集

  2. 执行 Vendorize 以通过运行 rip 所有依赖项/gems D:\projects\SomeLibrary\lib_vendor_

    D:\projects\SomeLibrary\lib>ruby -I..\..\Vendorize\lib -rvendorize some_lib.rb

  3. 通过运行在D:\projects\SomeLibrary\lib\_IRPackager_\some_lib.csproj 生成一个 c# 项目:

    D:\projects\SomeLibrary\lib>ruby -I..\..\IronRubyAppPackager\lib\IRPackager.rb some_lib.rb

  4. 将 some_lib.csproj 添加到我的解决方案中,将其升级到 .net4 并修复引用

  5. 此时,您可以通过运行以独立方式在 .NET 中运行项目
var Ruby = new EmbeddedRuby();
Ruby.Decoder = new Program.GZipDecoder();
Ruby.Mount("App");
Ruby.Run("gocardless.rb");

它成功了!我觉得太棒了!

实际上,此时我发现它在第 2 步中未能供应每个所需的库。 Vendorize 通过拦截 require 调用然后将调用的 rb 文件保存到 _Vendor_ 来工作 - 如果未执行 require(所以运行所有测试并希望测试覆盖率为 100%)它不会被拾取。

由于某种原因,它没有选择所需文件之一,即使有需求。最后,我通过复制我的库并使用bundle install --deployment 命令手动为 vendor 目录创建了内容。重复第 3 步和第 4 步,我就完成了……对吗?

不,当我运行生成的项目时,我收到了一些关于 no such file to load -- json/pure 的错误 - 我认为这是结合 Ironruby 没有原生 json 实现,我在进行手动供应,我不得不在今天有几点。

总结 - 这种方法非常接近有效,如果您的库及其依赖项与 ironruby 一起正常工作,并且您可以让 vendorize 正常工作。

我正在放弃并将库移植到 c# 的老式方式。

编辑:如下所述,rifraf 正在帮助我并正在考虑更新我正在使用的工具。看他(他)的空间!

【讨论】:

  • 感谢您的链接!这看起来很有希望。
  • 我过去也遇到过 json_pure 的问题。我知道有一个解决方案(我之前解决过)。如果我能回忆起,我会回复你...(也许试试igem install json_pure?)
  • 我刚刚尝试重复我的说明,现在库拥有的需要相关文件没有被正确供应... :(
  • +350 - 这是最接近问题解决方案的答案。只剩下几个问题来结束它。感谢您的帮助!
  • 塔!但是,如果您要走这条路,那么与 rifraf 取得联系是值得的 - 他是
猜你喜欢
  • 2015-10-25
  • 1970-01-01
  • 2011-01-09
  • 1970-01-01
  • 2019-04-20
  • 2013-03-03
  • 2012-12-06
  • 1970-01-01
  • 2017-12-22
相关资源
最近更新 更多