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

发布于 2025-01-06 07:10:52 字数 2247 浏览 1 评论 0 原文

我有一个 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 编译成 .exe (我认为它动态创建并编译 C# 项目),同时嵌入 ruby​​ 标准库。但看起来它只是嵌入了预构建的 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 的调用中(请参阅 https://github.com/kumaryu/irpack/blob/master/lib/irpack/packager.rb)。也许对将文件打包成可执行文件进行进一步研究会找到解决方案。我看到的问题是 gem 中的 ruby​​ 文件需要其他 ruby​​ 文件...程序集包中的 ruby​​ 文件可以需要同一包中的其他 ruby​​ 文件吗?

编辑3:

我还没有得到任何进一步的答案,但我有兴趣听到任何人的反馈,即使它只是一个链接或关于在哪里查看的建议。我是 msbuild 的新手,文档非常多。最初的网络搜索“msbuild embed zip package”没有显示任何相关内容。

I have a C# project in which I have embedded an IronRuby program. The project (including my ruby script) is compiled to an .exe file in Visual Studio 2010 for distribution. I'm using a pattern similar to this for bootstrapping the IronRuby script: http://pastebin.com/NKes1cyc (and Jimmy Schementi goes into more detail here: http://blog.jimmy.schementi.com/2009/12/ironruby-rubyconf-2009-part-35.html).

My problem: I would like to embed a gem (json_pure) in my C# assembly and call it from the ruby script.

Some resources I've found:

  1. In JRuby, you can easily package a gem into a jar file and then simply require the jar file at runtime - http://blog.nicksieger.com/articles/2009/01/10/jruby-1-1-6-gems-in-a-jar

  2. The irpack tool (at http://github.com/kumaryu/irpack) is capable of compiling Ruby into an .exe (I think it dynamically creates and compiles a C# project) while embedding the ruby standard library. But it looks like it is only embedding the pre-built IronRuby .dlls, not ruby .rb files. The approach this tool uses would work if I could figure out how to compile Ruby source files into a .dll.

How do I embed an IronRuby gem into a C# assembly (or compile an IronRuby gem to a .dll)?

EDIT:

Page 472 of IronRuby In Action ("Using External Libraries") explains how to require standard ruby libraries from within an embedded ruby file. It involves adding the folder(s) to the runtime search paths collection, as follows (edited for brevity and clarity):

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)

This approach assumes the host machine has IronRuby installed, but I want to embed ruby files (from a gem) into the assembly so it can be run without IronRuby pre-installed.

EDIT 2 (further research):

Reading through the source code of the irpack tool referenced above, I notice that Kumaryu is embedding resources into the final assembly via the System.IO.Packaging.Package class, and then passing the package into the call to msbuild (see https://github.com/kumaryu/irpack/blob/master/lib/irpack/packager.rb). Perhaps some further research into packaging files into an executable would lead to a solution. The problem I see is that ruby files in a gem require other ruby files... can a ruby file in an assembly package require other ruby files in the same package?

EDIT 3:

I haven't gotten any further to an answer yet, but I'd be interested to hear anyone's feedback, even if it's just a link or a suggestion about where to look. I'm new to msbuild, and the documentation is pretty hefty. An initial web search for "msbuild embed zip package" didn't reveal anything relevant.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

爱你是孤单的心事 2025-01-13 07:10:52

Require 是一个可以被重写的方法任何其他红宝石方法。我认为这就是原始 ruby​​ gems 包的工作方式,gems 会简单地覆盖 require

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

Require is a method that can be overridden like any other ruby method. I think that is how the original ruby gems package worked, gems would simply override require.

If you can package the gem into your .exe somehow, you can override require to load from the assembly.

段念尘 2025-01-13 07:10:52

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

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

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

I am working with https://stackoverflow.com/users/2086/mcintyre321 to get his library wrapped up into C#/IronRuby using my packaging code ( https://github.com/rifraf/IronRubyAppPackager#readme ).

There are some fixes needed in the vendorize step that are related to the later versions of Ruby having RubyGems embedded rather than loaded, but progress is being made.

His code requires 'json', and I have a trick to force it to use the Ruby implementation rather than the C-linkage .so files. This should mean that it will work with IronRuby ok. Will report back, or feel free to contact me with the source that you want to run.

夜深人未静 2025-01-13 07:10:52

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

报告:

我所进行的过程是...

  1. fork 和子模块所有项目(IronRubyEmbeddedApps, IronRubyAppPackager、Serfs 和 Vendorize)来自 https://github.com/rifraf,并将它们全部添加到 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 处生成 ac# 项目运行:

    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(“应用程序”);
Ruby.Run("gocardless.rb");

它成功了!我想太棒了!

实际上,此时我发现在步骤 2 中 Vendorize 每个所需的库都失败了。 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 正在帮助我并研究更新我正在使用的工具。注意他(他的)空间!

try this https://github.com/rifraf/IronRubyAppPackager#readme (or wait for me to report back on whether it works with the library I am trying to embed)

Reporting back:

The process I have gone to is...

  1. fork and submodule all the projects (IronRubyEmbeddedApps, IronRubyAppPackager, Serfs and Vendorize) from https://github.com/rifraf, and added them all into a VS solution. I updated all the projects to .NET4 and made them reference one another, rather than the included .net2 assemblies

  2. executed Vendorize to rip all the dependencies/gems D:\projects\SomeLibrary\lib_vendor_ by running:

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

  3. Generated a c# project at D:\projects\SomeLibrary\lib\_IRPackager_\some_lib.csproj by running:

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

  4. Added the some_lib.csproj to my solution, upgraded it to .net4 and fixed references

  5. At this point, you can run the project in .NET, standalone, by running
var Ruby = new EmbeddedRuby();
Ruby.Decoder = new Program.GZipDecoder();
Ruby.Mount("App");
Ruby.Run("gocardless.rb");

And it succeeded! Brilliant I thought!

Actually at this point I discovered that it had failed in step 2 to Vendorize every single required library. Vendorize works by intercepting require calls and then saving the called rb files off to the _Vendor_ - if require is not executed (so run all tests and hope test coverage is 100%) it won't be picked up.

For some reason, it wasn't picking up one of the required files, even though there was a require. In the end, I manually created the content for the vendor directory by copying my library in, and by using bundle install --deployment command. Repeat step 3 and 4 and I'm done... right?

Nope, I get some error about no such file to load -- json/pure when I run the generated project - I think this is something to do a combination of ironruby not having a native json implementation, me doing the manual vendorizing and me having to bodge things at several points today.

To conclude - this method very very nearly works, will work if your library and it dependencies work with ironruby properly, and you can get vendorize to work properly.

I'm giving up and porting the library to c# the old fashioned way.

edit: as mentioned below, rifraf is helping me and looking into updating the tools I was using. watch t(his) space!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文