Может ли Ruby импортировать .NET dll?

Я заинтересован в использовании/изучении RoR в проекте, где я должен использовать .NET dll. Способен ли Ruby импортировать .NET dll?


person Rafael Arie    schedule 05.11.2008    source источник


Ответы (7)


В то время как IronRuby быстро разговаривает с вашей .NET dll (это будет буквально вообще без кода), Microsoft отказалась от него, и у него никогда не было достаточно большого сообщества с открытым исходным кодом, чтобы продолжать его работу после этого события. Я бы не рекомендовал это в наши дни

Что касается COM-решения, это действительно может быть хорошим способом.

Вам не нужна библиотека RubyCOM, которая позволяет другим COM-объектам вызывать код ruby. Чтобы загрузить COM-объекты из ruby, вам просто нужна библиотека win32ole, которая входит в состав стандартной библиотеки для windows ruby.

Сможете ли вы загрузить dll из COM, будет зависеть от того, была ли .NET dll построена так, чтобы быть «видимой для Com». Платформа .NET определяет ComVisibleAttribute, который можно применять либо ко всей сборке, либо к определенным классам в сборке. Если для него установлено значение true либо для всей сборки, либо для каких-либо классов, то dll уже будет вызываться из COM без кода-оболочки.

Вот тест, который я сделал.

Создайте новый проект .NET dll (библиотека классов). Вот пример класса, который я использовал:

using System;
using System.IO;

namespace ComLib
{
    public class LogWriter
    {
        public void WriteLine( string line )
        {
            using( var log = new StreamWriter( File.OpenWrite( @"c:\log.file" ) ) )
            {
                log.WriteLine( line );
            }
        }
    }
}

Теперь в проекте визуальной студии есть каталог с именем Properties, который содержит AssemblyInfo.cs. В этом файле будет следующее

[assembly: ComVisible( false )]

Меняем ложь на истину. Если вы не хотите, чтобы каждый класс в сборке был открыт для COM, вы можете оставить для него значение false в AssemblyInfo.cs и вместо этого поместить его над каждым классом, который вы хотите предоставить, например так:

[ComVisible( true )]
public class LogWriter ....

Теперь щелкните правой кнопкой мыши сам проект dll и во всплывающем меню выберите «Свойства». В списке разделов выберите Build

Прокрутите вниз и установите флажок «Зарегистрироваться для COM-взаимодействия». Теперь, когда вы скомпилируете эту DLL, Visual Studio сделает все необходимое для загрузки информации COM в реестр. Обратите внимание, что если вы используете Vista, вам нужно запустить VS от имени администратора, чтобы это работало.

Теперь, когда это сделано, перекомпилируйте вашу dll, а затем создайте новый файл ruby.

В этом ruby-файле сделайте следующее:

require 'win32ole'

lib = WIN32OLE.new('[Solution name].ComLib.LogWriter')
lib.WriteLine('calling .net from ruby via COM, hooray!')

Где [Имя решения] должно быть заменено именем только что созданного решения (по умолчанию: "ClassLibrary1").

Руби этот рубиновый файл, и вуаля! вы должны увидеть, что текст записывается в c:\log.file.

Одна из проблем с этим решением заключается в том, что оно требует, чтобы .NET dll уже была Com Visible, или, если это не так, у вас есть возможность перекомпилировать ее. Если ни один из этих пунктов не соответствует действительности, возможно, вам придется рассмотреть другие варианты.

Удачи!

person Orion Edwards    schedule 05.11.2008
comment
Спасибо! Я проверю свойство comVisible dll, чтобы узнать, смогу ли я реализовать это решение. - person Rafael Arie; 06.11.2008
comment
Используя приведенный выше код, я получаю доступ к коду .Net dll и отлично справляюсь, но я хочу знать, как закрыть эту задачу... если я хочу использовать это часто.... если я использую один и тот же код, я часто не буду запускать его снова ... Есть ли способ закрыть/убить объект? - person Jeyavel; 23.12.2010
comment
Что вы подразумеваете под уничтожением объекта? Среда выполнения .NET управляет временем жизни COM-объектов за вас. Когда сборщик мусора запустится, он проверит и увидит, ссылается ли какой-либо код .NET на COM-объект, и если нет, то очистит его. Если код .NET все еще ссылается на него, его очистка вызовет ошибку. - person Orion Edwards; 29.12.2010
comment
Я знаю, что это старый вопрос, но установка флажка «Зарегистрировать для COM-взаимодействия» будет ли это работать только в том поле, на котором оно было скомпилировано, или мне придется зарегистрировать его в поле, которое я собираюсь использовать. - person Rig; 28.02.2015
comment
@OrionEdwards Я знаю, что это старый вопрос, но это действительно может спасти мой день, после регистрации я создал новый файл ruby, сохранил его на своем рабочем столе и добавил ruby. я получил эту ошибку: `инициализировать': неизвестный сервер OLE: Есть идеи, что я могу делать неправильно? - person Itzik984; 14.12.2016
comment
Как правильно зарегистрировать эту dll? - person Aleksey; 30.12.2016

Вы также можете написать собственную DLL-оболочку -> С#, используя управляемый С++.

Экспортируйте все функции, которые вы хотите, как вызовы C в DLL, например.

extern "C" __declspec ( dllexport ) void CallManagedMethod() {
   Something^ myManagedObject ...
}

Затем используйте FFI для вызова этой DLL из Ruby https://github.com/ffi/ffi.

person Rich    schedule 21.10.2011
comment
Привет! Я знаю, что это было давно, но: я пробовал этот подход, и все идет гладко, пока DLL-оболочка С++ не ссылается на метод .Net DLL во время выполнения. Затем я получаю сообщение «Не удалось загрузить файл или сборку в отношении .Net DLL». Есть идеи, почему? (Обе DLL находятся в той же папке, что и сценарий ruby, который экспортирует и вызывает функцию C++. Вызов .Net DLL работает нормально, если он вызывается из консольного приложения C++ из той же папки.) - person Vitaliy Prokopenko; 22.04.2021
comment
Не знаю, извини @ВиталийПрокопенко. Это сработало для меня еще в 2011 году. Я думаю, что Не удалось загрузить файл или сборку может произойти по разным причинам, и вам нужно будет включить дополнительную диагностическую информацию. Возможно, поднять новый вопрос с более подробной информацией? ГЛ - person Rich; 26.04.2021
comment
Спасибо, @Rich. На самом деле уже открыл один здесь - person Vitaliy Prokopenko; 26.04.2021

Если вы хотите использовать «обычный» рубин (поскольку я не думаю, что IronRuby полностью запускает RoR), вы можете использовать COM, т.е.

"Your Ruby Code" -> RubyCOM -> "COM-Callable Wrappers" -> "Your .NET objects"

RubyCom

Хотя это немного запутанно.

Изменить: лучший вариант на основе COM в другом месте ответов

person mackenir    schedule 05.11.2008

Другое дело - может быть лучше подумать об этом больше с точки зрения сервис-ориентированной архитектуры. Можете ли вы взять эту .NET DLL и предоставить ее как службу?

За кулисами вы можете писать модули Ruby на C, поэтому вы всегда можете написать взаимодействие, чтобы делать то, что вам нужно. Однако это ограничит ваше развертывание платформами Windows (я не пробовал Ruby-> Interop-> Mono)

Вот презентация, которую я сделал пару лет назад под названием Ruby для разработчиков C#. Это немного устарело (это было до того, как проект Джона Лама был включен в IronRuby), но может немного помочь.

person Cory Foy    schedule 05.11.2008
comment
Разоблачение .NET dll в качестве службы SOA - это путь, но мне нужно будет проверить проблемы безопасности, связанные с этим. - person Rafael Arie; 06.11.2008

Если вы используете IronRuby (реализация Ruby, построенная на .Net), то это должно быть возможно. Если вы уже используете .Net и хотите попробовать Ruby, возможно, вы захотите изучить IronRuby.

За пределами IronRuby я не уверен. Я сам не использовал Ruby, поэтому не знаю, на что он способен.

person Herms    schedule 05.11.2008

Хотя, насколько я понимаю, это мертвый проект, вы можете найти предыдущий проект RubyCLR Джона Лама (который сейчас отвечающий за IronRuby) интересный.

person Thibaut Barrère    schedule 06.11.2008

Если вы заинтересованы в совместном использовании ASP.NET MVC с IronRuby, вы можете проверить этот исходный код от Джимми - http://github.com/jschementi/ironrubymvc/tree/master

Наслаждаться!

person Jirapong    schedule 28.01.2009