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が読みだされ計算結果がダイアログに表示されるハズです。

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

    先述の例では、説明のために、ファイルを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」と同様の記述にて、実際の存在を確認しましょう。