如何将ruby gem嵌入到C#项目中并从嵌入式IronRuby脚本中获取它?

时间:2012-02-17 18:49:12

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

我有一个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,那么这个工具使用的方法就可以了。

  3. 如何将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的调用(参见{ {3}})。也许对将文件打包成可执行文件的进一步研究将导致解决方案。我看到的问题是gem require其他ruby文件中的ruby文件...汇编包中的ruby文件require在同一个包中的其他ruby文件中?

    编辑3:

    我还没有得到任何答案,但我有兴趣听到任何人的反馈,即使这只是一个关于在哪里看的链接或建议。我是msbuild的新手,而且文档非常庞大。对“msbuild embed zip package”的初步网络搜索没有透露任何相关内容。

3 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:3)

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

报告回来:

我去过的过程是......

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

  2. 执行Vendorize以通过运行来翻录所有依赖项/ 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. 此时,您可以通过运行
  6. 在.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的错误 - 我认为这是做一个没有本地json实现的ironruby,我做手动供应和我不得不躲避的组合今天在几个方面的事情。

    总而言之 - 如果您的库及其依赖项正确地与ironruby一起工作,这种方法非常有效,并且您可以使供应商正常工作。

    我放弃并以旧式的方式将库移植到c#。

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

答案 2 :(得分:3)

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

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

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