C#などで作った外部の「マネージドな.dll」の読み込み

概要

一般論の話をしますと、「C#」「VB.net」「C++/CLI」「F#」「JScript.net」などで作成したdllを「マネージドなアセンブリdll」として読み込む場合、
普通なら「読み込み対象となるdllファイル置き場の位置に大きな制約」があるのです。(ネットなどで調べてみてください)
特殊な設定でもしない限り、「exeと同じ場所か、dll名と同じ名前のサブフォルダに入れる」必要があります。

しかし、hmRb・IronRubyにはそのような制限は一切ありません。
好きなフォルダに置いた自作のマネージドな.dllを(特に署名などもなく)突如自由に読みだして利用可能です。

C#のソースから.dllを作成。

最小限のサンプルとするため、わかりやすい構成としましょう。

hmRb/IronRuby自体は、.NET Framework 4.0で構成されていますが、
あなたが利用する.dllは、.NET Framework 4.6など、hmRbより新しいバージョンのアセンブリでも大丈夫です!!
ここも普通の.NETの考え方の制限とは大きく異なるとここです。
あなたのPCに入っている.NET Frameworkの一番新しいバージョンで作成しても問題ありません。

  • ファイル名は「TestSample.dll」
  • 名前空間は「TestNameSpace」
  • クラス名は「TestClass」
  • メソッドは「TestFunc」

とします。

コンパイルし、TestSample.dllといった名前にしたとしましょう。

using System;

namespace TestNameSpace
{
    public class TestClass
    {
        public TestClass() { }
        public int TestFunc(int x)
        {
            return x + 3;
        }
    }
}

loadするIronRubyの例

$LOAD_PATH.push(...)をすることで、該当のパスに.dllを置いた場合に読み込み可能となります。
後は、普段通り、require 関数を利用して読み込みましょう。

ファイル名は、適当に「loaddll.rb」とでもしてみましょう。

# coding: utf-16
require 'mscorlib'
require "System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"

$currentmacrodirectory = $hm.Macro.Var['currentmacrodirectory']
$LOAD_PATH.push($currentmacrodirectory.to_s)  #.NETの文字列とRubyの文字列では差異がある。to_sを入れる必要がある。
#「$LOAD_PATH」ではなく、「$:」という特殊変数を使っても同じこと
# 高い優先順位でcurrentmacrodirectoryを加えるなら、pushの替わりに、unshiftを利用してください。

require 'TestSample'


$obj = TestNameSpace::TestClass.new
$total = $obj.TestFunc(10)
$loadclass = TestNameSpace::TestClass.to_s

$hm.Macro.Var['#total'] = $total;
$hm.Macro.Var['$loadclass'] = $loadclass;


$hm.debuginfo($total)

秀丸マクロに記述する.mac

一般的には、実行するマクロと同じ場所にdllを置くのが良いでしょうから、
このように「currentmacrodirectory」をIronRubyに渡して利用するのがテンプレートの1つとなるでしょう。

マクロ名は適当に「loaddlltest.mac」とでもしてみましょう。

#RB = loaddll( hidemarudir + "\\" + "hmRb.dll" );

#_ = dllfuncw(#RB, "DoFile", currentmacrodirectory + "\\loaddll.rb");

message(str(#total));
message($loadclass );

freedll( #RB );

好きなフォルダに置く

以上3つのファイルを好きなフォルダ(秀丸と一切関係ないフォルダでもよい)に置いて、
「loaddlltest.mac」を適当に秀丸に登録して実行してみてください。
.dllが読みだされ計算結果がダイアログに表示されるハズです。

PICTURE

マクロ内に手軽に簡易記述

先述の例では、説明のために、ファイルを2つに分けた例を提示しました。

hmRbでは、実行するマクロファイルと同じ場所(currentmacrodirectory)に、読み込み対象の.dllがある場合、
$LOAD_PATH にcurrentmacrodirectoryをpushする必要はありません。

以下のように簡潔な記述が可能です。

#RB = loaddll( hidemarudir + @"\hmRb.dll" );

#_ = dllfuncw( #RB, "DoString", R"IRONRUBY(

require 'mscorlib'
load_assembly "System"
require 'TestSample' # load_assembly 'TestSample' でも同じ


$obj = TestNameSpace::TestClass.new
$total = $obj.TestFunc(10)
$loadclass = TestNameSpace::TestClass.to_s

$hm.Macro.Var['#total'] = $total;
$hm.Macro.Var['$loadclass'] = $loadclass;

$hm.debuginfo($total)

$hm.Macro.Eval(<<-'MACRO'
    message(str(#total));
    message($loadclass );
MACRO
);

)IRONRUBY"
);

freedll( #RB );

既存のRuby標準ライブラリや.NET標準ライブラリと名前が被らないように注意

Ruby標準ライブラリや.NET標準ライブラリと同じ名前の.dllやクラスを生成するのは
読み込み順番が少し変わっただけで挙動が変わるため、混乱のもとですのでやめましょう。
既存のライブラリとしてそれが存在するのかどうかは、以下のような形で軽い確認できます。

ironrubyのコマンドラインで...

ir -rcmath -e ""

などとする

ir -rmylib -e ""

としてLoadErrorが出れば、それ(=mylib)は既存のライブラリには存在しない。

ir -rSystem -e ""

CLRのSystemが読まれるので、Errorが出ない。すなわち存在する。

より厳密なチェックをするならば、
実際に、このページ内にある「require」や「load_assembly」と同様の記述にて、実際の存在を確認しましょう。

PICTURE