reflection.d

D で Reflection 。言語の助けは借りない。今までの謎の作業の集大成的なもの。(参考: ccall_direct,gdcc,dfilt)

http://shinh.skr.jp/d/reflection.tar.bz2

class Test {
    void test_func1() { std.stream.stdout.writeLine("func1"); }
    void test_func2() { std.stream.stdout.writeLine("func2"); }
    void test_func3() { std.stream.stdout.writeLine("func3"); }
    int test_ignore1() { std.stream.stdout.writeLine("error"); return 0; }
    void test_ignore2(int i) { std.stream.stdout.writeLine("error"); }
    void ignore() { std.stream.stdout.writeLine("error"); }
}

int main(char args) {
    Reflection.init(args[1]);

    Test test = new Test();
    Class c = Class.forName("test_reflection.Test");
    if (c !== null) {
        foreach (Method m; c.methods) {
            std.stream.stdout.writeLine("found: " ~ m.name);
            if (m.name.length >= 4 && m.name[0..4] == "test" &&
                m.type.func.ret.builtin.type == Builtin.Type.VOID &&
                m.type.func.args.length == 0)
            {
                std.stream.stdout.writeLine("invoke: " ~ m.name);
                (cast(void (*)(Test))m.address)(test);
            }
        }
    }
    else {
        std.stream.stdout.writeLine("cannot get test class");
    }
}

実行すると以下のような感じ。

found: ignore
found: test_func1
invoke: test_func1
func1
found: test_func2
invoke: test_func2
func2
found: test_func3
invoke: test_func3
func3
found: test_ignore1
found: test_ignore2

アーカイブ中の build.sh を見ればコンパイル法、実行法がわかります。 Windows では gdc と nm があればたぶんできます。まあ無いだろうな。

オンデマンドリフレクションである点、アドレスを適当にキャストしてメソッドを呼ぶ点がいかにもネイティブバイナリ吐く言語っぽくて良い気がします。

問題点, TODO: 命名むちゃくちゃ。ソースむちゃくちゃ。 Windowsdmdコンストラクタ。テンプレート(下記参照)。 dUnit 。 serialize.d 。

なにかあれば下記メールアドレスへ。
shinichiro.hamaji _at_ gmail.com
shinichiro.h