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: 命名むちゃくちゃ。ソースむちゃくちゃ。 Windows の dmd 。コンストラクタ。テンプレート(下記参照)。 dUnit 。 serialize.d 。