Как вставить рубиновый камень в проект С# и потребовать его от встроенного IronRuby script?
У меня есть проект С#, в который я встроил программу IronRuby. Проект (включая мой ruby script) скомпилирован в файл .exe в Visual Studio 2010 для распространения. Я использую шаблон, подобный этому для начальной загрузки IronRuby script: http://pastebin.com/NKes1cyc (и Джимми Schementi более подробно описывает здесь: http://blog.jimmy.schementi.com/2009/12/ironruby-rubyconf-2009-part-35.html).
Моя проблема: я хотел бы встроить gem (json_pure) в свою сборку С# и вызвать его из ruby script.
Некоторые ресурсы, которые я нашел:
-
В JRuby вы можете легко упаковать драгоценный камень в файл jar, а затем просто потребовать файл jar во время выполнения - http://blog.nicksieger.com/articles/2009/01/10/jruby-1-1-6-gems-in-a-jar
-
Инструмент irpack (http://github.com/kumaryu/irpack) способен скомпилировать Ruby в .exe(я думаю, что он динамически создает и компилирует проект С#) при встраивании стандартной библиотеки ruby. Но похоже, что это только встраивание готовых файлов IronRuby.dlls, а не ruby .rb. Подход, который использует этот инструмент, будет работать, если я смогу выяснить, как скомпилировать исходные файлы Ruby в .dll.
Как встроить жемчужину IronRuby в сборку С# (или скомпилировать жемчужину IronRuby в .dll)?
EDIT:
Страница 472 IronRuby In Action ( "Использование внешних библиотек" ) объясняет, как требовать стандартных рубиновых библиотек из встроенного рубинового файла. Это связано с добавлением папки (ов) в коллекцию путей поиска во время выполнения, следующим образом (отредактировано для краткости и ясности):
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, но я хочу вставить рубиновые файлы (из жемчужины) в сборку, чтобы он мог запускаться без предварительной установки IronRuby.
EDIT 2 (дальнейшие исследования):
Чтение исходного кода инструмента irpack, упомянутого выше, я замечаю, что Kumaryu внедряет ресурсы в финальную сборку через класс System.IO.Packaging.Package, а затем передает пакет в вызов msbuild (см. https://github.com/kumaryu/irpack/blob/master/lib/irpack/packager.rb). Возможно, некоторые дальнейшие исследования по упаковыванию файлов в исполняемый файл приведут к решению. Проблема, которую я вижу, в том, что рубиновые файлы в gem require
других рубиновых файлах... может ли рубиновый файл в сборке require
других рубиновых файлов в одном пакете?
ИЗМЕНИТЬ 3:
Я еще не получил ответа на этот вопрос, но мне было бы интересно услышать любую обратную связь, даже если это просто ссылка или предложение о том, где искать. Я новичок в msbuild, и документация довольно здоров. Первоначальный веб-поиск "msbuild embed zip package" не выявил ничего значимого.
Ответы
Ответ 1
Требовать - это метод, который можно переопределить, как любой другой метод ruby. Я думаю, что именно так работал оригинальный пакет рубиновых драгоценных камней, драгоценные камни просто переопределили require
.
Если вы можете каким-то образом упаковать драгоценный камень в ваш .exe, вы можете переопределить require
для загрузки из сборки.
Ответ 2
попробуйте https://github.com/rifraf/IronRubyAppPackager#readme (или дождитесь, пока я отчитаюсь о том, работает ли он с библиотекой, которую я пытаюсь встроить)
Отчетность:
Процесс, к которому я пошел, - это...
-
fork и подмодуль всех проектов (IronRubyEmbeddedApps, IronRubyAppPackager, Serfs and Vendorize) из https://github.com/rifraf и добавили их все в решение VS. Я обновил все проекты до .NET4 и сделал их ссылкой друг на друга, а не включенные сборки .net2
-
выполнил команду Vendorize для копирования всех зависимостей/драгоценных камней D:\projects\SomeLibrary\lib_vendor_
путем запуска:
D:\projects\SomeLibrary\lib>ruby -I..\..\Vendorize\lib -rvendorize some_lib.rb
-
Сгенерировал проект С# в D:\projects\SomeLibrary\lib\_IRPackager_\some_lib.csproj
, выполнив:
D:\projects\SomeLibrary\lib>ruby -I..\..\IronRubyAppPackager\lib\IRPackager.rb some_lib.rb
-
Добавил some_lib.csproj к моему решению, обновил его до .net4 и фиксированных ссылок
- На этом этапе вы можете запустить проект в .NET, автономно, выполнив
var Ruby = new EmbeddedRuby();
Ruby.Decoder = new Program.GZipDecoder();
Ruby.Mount("App");
Ruby.Run("gocardless.rb");
И это сработало! Блестящий я думал!
На самом деле в этот момент я обнаружил, что он не выполнил шаг 2 для Vendorize каждой отдельной требуемой библиотеки. Vendorize работает, перехватывая вызовы require
, а затем сохраняя вызываемые rb файлы на _Vendor_
- если require
не выполняется (поэтому для запуска всех тестов и покрытия тестирования надежда 100%) он не будет поднят.
По какой-то причине он не собирал один из необходимых файлов, хотя требовалось. В конце концов, я вручную создал контент для каталога поставщика, скопировав мою библиотеку и используя команду bundle install --deployment
. Повторите шаги 3 и 4, и я закончу... правильно?
Нет, я получаю некоторую ошибку в no such file to load -- json/pure
при запуске сгенерированного проекта - я думаю, что это что-то, что можно сделать с помощью комбинации ironruby, не имеющей встроенной json-реализации, я делаю ручную вендоризацию, и мне приходится делать вещи в сегодня несколько пунктов.
В заключение - этот метод очень почти работает, будет работать, если ваша библиотека и ее зависимости будут работать с ironruby должным образом, и вы можете заставить vendorize работать правильно.
Я сдаюсь и портирую библиотеку на С# старомодным способом.
edit: как упоминалось ниже, rifraf помогает мне и изучает обновляемые инструменты, которые я использовал. следите за его пространством!
Ответ 3
Я работаю с https://stackoverflow.com/users/2086/mcintyre321, чтобы получить его библиотеку, завернутую в С#/IronRuby, используя мой код упаковки (https://github.com/rifraf/IronRubyAppPackager#readme).
На этапе vendorize есть некоторые исправления, связанные с более поздними версиями Ruby с встроенным RubyGems, а не с загрузкой, но прогресс выполняется.
Его код требует "json", и у меня есть трюк, чтобы заставить его использовать реализацию Ruby, а не файлы Cso-link.so. Это должно означать, что он будет работать с IronRuby в порядке. Откроется отчет или не стесняйтесь обращаться ко мне с источником, который вы хотите запустить.