digitalmars.D - An experimental reflection library
- s31552 mail.ecc.u-tokyo.ac.jp (67/67) Aug 03 2004 I implemented a reflection library in D experimentally. Because now
- parabolis (6/11) Aug 03 2004 Well done! I was just discussing the possibility of reflection
- Garett Bass (7/7) Aug 03 2004 I must admit, I haven't entirely grokked your reflection implementation....
- shinichiro.h (22/28) Aug 03 2004 Yes, I think field infomation is needed. Object serialization is one
- Mickey Finn (3/70) Aug 04 2004 Nice!
I implemented a reflection library in D experimentally. Because now DMD compiler does not support reflection, my implementation is not smart. If you want to use my reflection library, you should prepare a file which contains symbol table using /MAP linker option. (or nm(1) command on Unix). The library read the symbol table from the file and demangle symbols. Since the symbols of D language has type infomations, the symbol table is enough to implement reflection. You can download the library here: http://user.ecc.u-tokyo.ac.jp/~s31552/wp/d/reflection.tar.bz2 The file contains four files, reflection.d is the main library code, test_reflection.d is a test code, and build_*.sh are build scripts. The library supports both DMD and GDC. I check this library with DMD&Windows, DMD&Linux, GDC&Linux, GDC&MacOSX. Please note that the library has a lot of todos to simulate real reflection and the library will be no use if DMD supports reflection. A sample code of my library is the following: import reflection; 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"); } } The above program iterates methods of "Test" class, and invoke the each method when the name of the method starts with "test" and the method returns void and requires no arguments. When you run the program, you'll obtain the following message in stdout: 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 Please comment if you are interested in this library. ------------------ shinichiro.h s31552 mail.ecc.u-tokyo.ac.jp http://user.ecc.u-tokyo.ac.jp/~s31552/wp/
Aug 03 2004
s31552 mail.ecc.u-tokyo.ac.jp wrote:I implemented a reflection library in D experimentally. Because now DMD compiler does not support reflection, my implementation is not smart.Please comment if you are interested in this library.Well done! I was just discussing the possibility of reflection and I believe the thing you want to see is for ClassInfo to tell you what kinds of fields the instantiated object contains and in what order they appear. Is there anything else that you would need for full reflection?
Aug 03 2004
I must admit, I haven't entirely grokked your reflection implementation. I just want to add that, for serialization purposes, it would also be very handy if there were some means of reflecting upon a class's member variables. This would make it easy to create templates that could serialize/deserialize an object to/from a stream. Bravo, Garett
Aug 03 2004
Well done! I was just discussing the possibility of reflection and I believe the thing you want to see is for ClassInfo to tell you what kinds of fields the instantiated object contains and in what order they appear. Is there anything else that you would need for full reflection?Yes, I think field infomation is needed. Object serialization is one of the big motivation for reflection. And if I continue to consider the demangle-base reflection, the name mangling rule of D language is not good now. We cannot distinguish C_f.C and C!(float): class C_f { class C {} } class C(T) {} C!(float) c; // They have the same "_Class_4test3C_f1C" symbol. // So this code causes link error. And I think implementing a user-friendly interface of constructor is difficult. We can construct objects manually with _d_newclass function. The code which call constructor will be like following: class Test { this(int i) {} } Class c = Class.forName(`test.Test`); void* ctor = c.getCtor(); ClassInfo ci = c.getClassInfo(); Object otmp = _d_newclass(ci); Object o = (cast(Object(*)(ClassInfo, int))ctor)(otmp, 1); It is complicated. ------------------ shinichiro.h
Aug 03 2004
Nice! <s31552 mail.ecc.u-tokyo.ac.jp> wrote in message news:20040804140404.05de4e3a.s31552 mail.ecc.u-tokyo.ac.jp...I implemented a reflection library in D experimentally. Because now DMD compiler does not support reflection, my implementation is not smart. If you want to use my reflection library, you should prepare a file which contains symbol table using /MAP linker option. (or nm(1) command on Unix). The library read the symbol table from the file and demangle symbols. Since the symbols of D language has type infomations, the symbol table is enough to implement reflection. You can download the library here: http://user.ecc.u-tokyo.ac.jp/~s31552/wp/d/reflection.tar.bz2 The file contains four files, reflection.d is the main library code, test_reflection.d is a test code, and build_*.sh are build scripts. The library supports both DMD and GDC. I check this library with DMD&Windows, DMD&Linux, GDC&Linux, GDC&MacOSX. Please note that the library has a lot of todos to simulate real reflection and the library will be no use if DMD supports reflection. A sample code of my library is the following: import reflection; 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"); } } The above program iterates methods of "Test" class, and invoke the each method when the name of the method starts with "test" and the method returns void and requires no arguments. When you run the program, you'll obtain the following message in stdout: 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 Please comment if you are interested in this library. ------------------ shinichiro.h s31552 mail.ecc.u-tokyo.ac.jp http://user.ecc.u-tokyo.ac.jp/~s31552/wp/
Aug 04 2004