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

概要

hmJSは、好きなフォルダに置いた自作のマネージドな.dllを(特に署名などもなく)突如自由に読みだして利用することが可能です。

「C#」はもちろんのこと「VB.net」「C++/CLI」「F#」「JScript.net」などで作成したdllを読み込むことが出来ます。

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

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

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

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

とします。

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

using System;

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

        public String TestFuncStr(String s)
        {
            return s + s;
        }

        // 可変長引数
        public int TestFuncMax(params int[] a)
        {
            int max = a[0];
            for(int i=1; i<a.Length; ++i)
            {
              if(max < a[i])
                max = a[i];
            }
            return max;
        }
    }
}

loadするhmJSの例

host.libを利用することでアセンブリを読み込むことが出来ます。

読み込めたマネージdllの内容は、hmJSに取り込まれ、直接JavaScriptで以下のように利用可能です。

// マクロが置いてある場所に.dllが置いてあるものとする。
// マクロが置いてある場所と、.dllが置いてある場所が違うなら、「"C:/xxx/xxx/xx.dll"」などと具体的にフルパスを指定すれば良い
#JS = loaddll( hidemarudir + @"\hmJS.dll" );

#_ = dllfuncw( #JS, "DoString", R"JS(

currentmacrodirectory = hm.Macro.Var('currentmacrodirectory');
var addlib = host.lib(currentmacrodirectory + "/TestSample.dll");

var obj = new addlib.TestNameSpace.TestClass();
result_num = obj.TestFuncNum(10)
result_str = obj.TestFuncStr("あいう")

result_max = obj.TestFuncMax(1, 100, -5, 101, 10)
hm.debuginfo(result_max)

result_max = obj.TestFuncMax(1, 10)
hm.debuginfo(result_max)

hm.Macro.Var('#result_num', result_num);
hm.Macro.Var('$result_str', result_str);

)JS"
);

message(str(#result_num));
message($result_str);

freedll( #JS );

hidemarudirやcurrentmacrodirectoryは読み込み対象ディレクトリとなっている

hmJSでは、実行するマクロファイルと同じ場所(currentmacrodirectory)に、読み込み対象の.dllがある場合、
フルパスを指定せず、以下のように.NET Frameworkの既存のライブラリを呼び出すのと同様の感覚で、読み込んで利用することが出来ます。

var addlib = host.lib("TestSample"); // hidemarudir もしくは、currentmacrodirectoryにあるTestSample.dllのロードを試みる

自作の個人的なディレクトリを、「.dll(アセンブリ)の置き場所」として認識させる

アセンブリの.dllは本来配置場所が自由ではありません。
これを特別に追加するため、「IronPythonなら、sys.path.append」、「IronRubyなら、$LOAD_PATH.push」があります。

  • AssemblyPath.Add(...)

    これらと同様の機能を提供するため、hmJSには、「AssemblyPath」という変数名の「List<String>型」のオブジェクトを提供しています。
    ここにパスを加えていくことで、該当のフォルダにあるアセンブリを自然な形で読み込むことが出来ます。
    特にC#など自作の.dllの中から、他の.dllを読み込んでおり、その両方を該当のディレクトリに入れている場合は、この設定が必須です。

  • host.lib(clr, "...")

    また、上述までのソースとは異なり、「host.lib」関数の第1引数に、「clr」を指定し、第2引数に読み込みたいアセンブリを指定することで、
    読み込み対象の.dll内の内容は、clrオブジェクトへと追加されていきます。

#JS = loaddll( hidemarudir + @"\hmJS.dll" );

#_ = dllfuncw( #JS, "DoString", R"JS(

// C:\aaaのフィルダは.dllの置き場所として加える。
AssemblyPath.Add("C:/aaa");

// var addlib = host.lib("C:/aaa/TestSample.dll"); と別変数に受けるのではなく、既存の「clr」にたしこむ形で受
host.lib(clr, "TestSample");

var obj = new clr.TestNameSpace.TestClass();
result_num = obj.TestFuncNum(10)
result_str = obj.TestFuncStr("あいう")

result_max = obj.TestFuncMax(1, 100, -5, 101, 10)
hm.debuginfo(result_max)

result_max = obj.TestFuncMax(1, 10)
hm.debuginfo(result_max)

hm.Macro.Var('#result_num', result_num);
hm.Macro.Var('$result_str', result_str);

)JS"
);

freedll( #JS );