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









"Garett Bass" <gtbass studiotekne.com> 