문제

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.

도움이 되었습니까?

해결책

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.

다른 팁

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.

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!

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top