Как встроить рубиновый гем в проект C # и требовать его от встроенного скрипта IronRuby? - PullRequest
16 голосов
/ 17 февраля 2012

У меня есть проект на C #, в который я встроил программу IronRuby. Проект (включая мой скрипт ruby) скомпилирован в файл .exe в Visual Studio 2010 для распространения. Я использую шаблон, подобный этому, для начальной загрузки скрипта IronRuby: http://pastebin.com/NKes1cyc (и Джимми Схементи более подробно расскажет здесь: http://blog.jimmy.schementi.com/2009/12/ironruby-rubyconf-2009-part-35.html).

Моя проблема: я хотел бы встроить гем (json_pure) в мою сборку C # и вызвать его из сценария ruby.

Некоторые ресурсы, которые я нашел:

  1. В JRuby вы можете легко упаковать гем в файл 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 в сборку C # (или компилировать гем IronRuby в .dll)?

РЕДАКТИРОВАТЬ:

Страница 472 из IronRuby In Action («Использование внешних библиотек») объясняет, как требовать стандартные библиотеки 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 ​​(из гема) в сборку, чтобы ее можно было запускать без предустановленной версии IronRuby.

РЕДАКТИРОВАТЬ 2 (дальнейшее исследование):

Читая исходный код инструмента irpack, упомянутого выше, я заметил, что Kumaryu встраивает ресурсы в окончательную сборку через класс System.IO.Packaging.Package, а затем передает пакет в вызов msbuild (см. https://github.com/kumaryu/irpack/blob/master/lib/irpack/packager.rb). Возможно, некоторые дальнейшие исследования по упаковке файлов в исполняемый файл приведут к решению. Проблема, которую я вижу, состоит в том, что файлы ruby ​​в геме require другие файлы ruby ​​... могут быть файлом ruby ​​в пакете сборки require другие файлы ruby ​​в том же пакете?

РЕДАКТИРОВАТЬ 3:

Я еще не дошел до ответа, но мне было бы интересно услышать чей-либо отзыв, даже если это просто ссылка или предложение о том, где искать. Я новичок в msbuild, и документация довольно здоровенная. Первоначальный веб-поиск "msbuild embed zip package" не выявил ничего уместного.

Ответы [ 3 ]

3 голосов
/ 28 февраля 2012

попробуйте https://github.com/rifraf/IronRubyAppPackager#readme (или подождите, пока я сообщу о том, работает ли он с библиотекой, которую я пытаюсь встроить)

Отчетность:

Процесс Iперешли к ...

  1. разветвлению и субмодулированию всех проектов (IronRubyEmbeddedApps, IronRubyAppPackager, Serfs и Vendorize) из https://github.com/rifraf, и добавили их все в решение VS.Я обновил все проекты до .NET4 и заставил их ссылаться друг на друга, а не на включенные сборки .net2

  2. выполнил Vendorize, чтобы разорвать все зависимости / гемы D:\projects\SomeLibrary\lib_vendor_, запустив:

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

  3. Создан проект ac # в D:\projects\SomeLibrary\lib\_IRPackager_\some_lib.csproj, запустив:

    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%), он не будет получен.

По какой-то причине он не собирал один из требуемых файлов, хотя и требовался.В конце я вручную создал контент для каталога vendor , скопировав свою библиотеку и используя команду bundle install --deployment.Повторите шаги 3 и 4, и я закончил ... правильно?

Нет, я получаю некоторую ошибку о no such file to load -- json/pure, когда я запускаю сгенерированный проект - я думаю, что это что-то, чтобы сделать комбинацию из Ironruby, а неимея нативную реализацию json, я занимаюсь вендорингом вручную, и мне сегодня приходится навязывать вещи в нескольких точках.

В заключение - этот метод очень почти работает, будет работать, если ваша библиотека и ее зависимости правильно работают с ironrubyи вы можете заставить вендор работать должным образом.

Я сдаюсь и портирую библиотеку на c # по старинке.

edit: как упоминалось ниже, rifraf помогает мне и ищетв обновлении инструментов, которые я использовал.смотреть т (его) пространство!

3 голосов
/ 01 марта 2012

Я работаю с https://stackoverflow.com/users/2086/mcintyre321, чтобы обернуть его библиотеку в C # / IronRuby, используя мой код упаковки (https://github.com/rifraf/IronRubyAppPackager#readme).

В поставщике есть некоторые исправленияшаг, связанный с более поздними версиями Ruby, в которых RubyGems встроен, а не загружен, но прогресс уже достигнут.

Его код требует 'json', и у меня есть хитрость, чтобы заставить его использовать реализацию Ruby, а нечем файлы .so C-linkage.Это должно означать, что с IronRuby все будет нормально.Отзовитесь или свяжитесь со мной с источником, который вы хотите запустить.

3 голосов
/ 26 февраля 2012

Require - метод , который можно переопределить, как и любой другой метод ruby.Я думаю, что так работал оригинальный пакет ruby ​​gems, gems просто переопределяет require.

Если вы можете каким-то образом упаковать гем в ваш .exe, вы можете переопределить require для загрузки из сборки.

...