digitalmars.D - Introspection/Reflection/etc on Linux
- J Arrizza (14/14) Oct 18 2011 I'm trying to write some sample code to:
- Robert Jacques (14/28) Oct 18 2011 You could try out my improved variant implementation:
- J Arrizza (24/37) Nov 01 2011 Robert,
- Robert Jacques (3/22) Nov 02 2011 (I apologize if this gets sent twice, my newsreader is acting up)
- J Arrizza (20/54) Nov 03 2011 Robert,
- J Arrizza (6/21) Nov 03 2011 PS, this version works and prints "10" for the length:
- Robert Jacques (2/30) Nov 03 2011 Thanks John for tracking this down and finding a work around. It seems t...
- Robert Jacques (2/21) Nov 07 2011 Nope, (hopefully) just patches. I maintain a list of the bugzilla patche...
- Jacob Carlborg (22/36) Oct 19 2011 How about doing something like this:
- J Arrizza (31/31) Oct 19 2011 Just noticed an odd thing when I was trying Jacob's code.
- Jacob Carlborg (6/37) Oct 19 2011 For Object.factory you need the fully qualified name, i.e.
- J Arrizza (10/14) Oct 19 2011 Yup, didn't check for null, damn it. Can I blame it on working on it at
- Jacob Carlborg (6/20) Oct 19 2011 The fully qualified class name includes the module the class is defined
- Jacob Carlborg (5/19) Oct 19 2011 Runtime reflection by inspecting the symbol table of the currently
- J Arrizza (19/23) Oct 23 2011 Jacob, by the way, I did try flectioned and unfortunately it failed to
I'm trying to write some sample code to: 1 create an object via it's name 2 search an object for it's functions 3 call a static function in a class 4 call a non-static function in an object DMD 2.0. I found this: http://www.digitalmars.com/d/archives/digitalmars/D/announce/Runtime_reflection_9949.html Ubuntu. Any other avenues I can chase? TIA, John
Oct 18 2011
On Tue, 18 Oct 2011 12:48:47 -0400, J Arrizza <cppgent0 gmail.com> wrote:I'm trying to write some sample code to: 1 create an object via it's name 2 search an object for it's functions 3 call a static function in a class 4 call a non-static function in an object DMD 2.0. I found this: http://www.digitalmars.com/d/archives/digitalmars/D/announce/Runtime_reflection_9949.html Ubuntu. Any other avenues I can chase? TIA, JohnYou could try out my improved variant implementation: https://jshare.johnshopkins.edu/rjacque2/public_html/variant.mht https://jshare.johnshopkins.edu/rjacque2/public_html/variant.d Example: import variant; class Foo { int x; } void main(string[] args) { Variant.__register!Foo; Variant var = Object.factory( typeid(Foo).toString ); var.__reflect("x",Variant(10)); // or explicitly assert(var.__reflect("x") == 10); return; }
Oct 18 2011
Robert, I tried using variant.d using your exact test program below and I got compiler errors: $ dmd variant.d dtest.d variant.d(273): Error: no property 'length' for type 'Result' variant.d(273): Error: no property 'length' for type 'Result' variant.d(274): Error: no property 'length' for type 'Result' variant.d(274): Error: no property 'length' for type 'Result' variant.d(274): Error: no property 'length' for type 'Result' variant.d(275): Error: no property 'length' for type 'Result' variant.d(277): Error: no property 'length' for type 'Result' variant.d(277): Error: no property 'length' for type 'Result' variant.d(277): Error: no property 'length' for type 'Result' variant.d(277): Error: no property 'length' for type 'Result' variant.d(280): Error: no property 'length' for type 'Result' $ dmd -v DMD64 D Compiler v2.055 Am I missing a switch or something? John On Tue, Oct 18, 2011 at 8:13 PM, Robert Jacques <sandford jhu.edu> wrote:You could try out my improved variant implementation: https://jshare.johnshopkins.**edu/rjacque2/public_html/**variant.mht<https://jshare.johnshopkins.edu/rjacque2/public_html/variant.mht> https://jshare.johnshopkins.**edu/rjacque2/public_html/**variant.d<https://jshare.johnshopkins.edu/rjacque2/public_html/variant.d> Example: import variant; class Foo { int x; } void main(string[] args) { Variant.__register!Foo; Variant var = Object.factory( typeid(Foo).toString ); var.__reflect("x",Variant(10))**; // or explicitly assert(var.__reflect("x") == 10); return; }-- John blog: http://arrizza.blogspot.com/ web: http://www.arrizza.com/
Nov 01 2011
On Tue, 01 Nov 2011 14:42:42 -0400, J Arrizza <cppgent0 gmail.com> wrote:Robert, I tried using variant.d using your exact test program below and I got compiler errors: $ dmd variant.d dtest.d variant.d(273): Error: no property 'length' for type 'Result' variant.d(273): Error: no property 'length' for type 'Result' variant.d(274): Error: no property 'length' for type 'Result' variant.d(274): Error: no property 'length' for type 'Result' variant.d(274): Error: no property 'length' for type 'Result' variant.d(275): Error: no property 'length' for type 'Result' variant.d(277): Error: no property 'length' for type 'Result' variant.d(277): Error: no property 'length' for type 'Result' variant.d(277): Error: no property 'length' for type 'Result' variant.d(277): Error: no property 'length' for type 'Result' variant.d(280): Error: no property 'length' for type 'Result' $ dmd -v DMD64 D Compiler v2.055 Am I missing a switch or something? John(I apologize if this gets sent twice, my newsreader is acting up) Nope, (hopefully) just patches. I maintain a list of the bugzilla patches (i.e. http://d.puremagic.com/issues/show_bug.cgi?id=5155) I've applied at the top of the file. But, mostly those are so DMD doesn't ICE; I've never seen this particular error before and am not sure how to interpret it. Hmm.. I don't use a Result type, but std.algoroithm does and one of the patches I always use is 6256 (http://d.puremagic.com/issues/show_bug.cgi?id=6256), which addresses length for Map.
Nov 02 2011
Robert, This stub shows the issue: import std.stdio; import std.range; void main(string[] args) { string id = "somestring"; auto rid = retro(id); writeln(rid.length); } $: dmd dtest.d dtest.d(8): Error: no property 'length' for type 'Result' I haven't applied either patch you mentioned below. Neither patch seems to address retro() or Result... John On Wed, Nov 2, 2011 at 6:43 AM, Robert Jacques <sandford jhu.edu> wrote:On Tue, 01 Nov 2011 14:42:42 -0400, J Arrizza <cppgent0 gmail.com> wrote: Robert,-- John blog: http://arrizza.blogspot.com/ web: http://www.arrizza.com/I tried using variant.d using your exact test program below and I got compiler errors: $ dmd variant.d dtest.d variant.d(273): Error: no property 'length' for type 'Result' variant.d(273): Error: no property 'length' for type 'Result' variant.d(274): Error: no property 'length' for type 'Result' variant.d(274): Error: no property 'length' for type 'Result' variant.d(274): Error: no property 'length' for type 'Result' variant.d(275): Error: no property 'length' for type 'Result' variant.d(277): Error: no property 'length' for type 'Result' variant.d(277): Error: no property 'length' for type 'Result' variant.d(277): Error: no property 'length' for type 'Result' variant.d(277): Error: no property 'length' for type 'Result' variant.d(280): Error: no property 'length' for type 'Result' $ dmd -v DMD64 D Compiler v2.055 Am I missing a switch or something? John(I apologize if this gets sent twice, my newsreader is acting up) Nope, (hopefully) just patches. I maintain a list of the bugzilla patches (i.e. http://d.puremagic.com/issues/**show_bug.cgi?id=5155<http://d.puremagic.com/issues/show_bug.cgi?id=5155>) I've applied at the top of the file. But, mostly those are so DMD doesn't ICE; I've never seen this particular error before and am not sure how to interpret it. Hmm.. I don't use a Result type, but std.algoroithm does and one of the patches I always use is 6256 (http://d.puremagic.com/** issues/show_bug.cgi?id=6256<http://d.puremagic.com/issues/show_bug.cgi?id=6256>), which addresses length for Map.
Nov 03 2011
PS, this version works and prints "10" for the length: string id = "somestring"; auto rid = retro(id); //writeln(rid.length); writeln(rid.source.length); On Thu, Nov 3, 2011 at 3:26 AM, J Arrizza <cppgent0 gmail.com> wrote:Robert, This stub shows the issue: import std.stdio; import std.range; void main(string[] args) { string id = "somestring"; auto rid = retro(id); writeln(rid.length); } $: dmd dtest.d dtest.d(8): Error: no property 'length' for type 'Result' I haven't applied either patch you mentioned below. Neither patch seems to address retro() or Result... John
Nov 03 2011
On Thu, 03 Nov 2011 06:28:30 -0400, J Arrizza <cppgent0 gmail.com> wrote:PS, this version works and prints "10" for the length: string id = "somestring"; auto rid = retro(id); //writeln(rid.length); writeln(rid.source.length); On Thu, Nov 3, 2011 at 3:26 AM, J Arrizza <cppgent0 gmail.com> wrote:Thanks John for tracking this down and finding a work around. It seems that the behavior of retro changed between 2.053 and 2.055. As you've probably already found, the errors are in the typeinfo2stringof function on line 245 of the currently uploaded variant.Robert, This stub shows the issue: import std.stdio; import std.range; void main(string[] args) { string id = "somestring"; auto rid = retro(id); writeln(rid.length); } $: dmd dtest.d dtest.d(8): Error: no property 'length' for type 'Result' I haven't applied either patch you mentioned below. Neither patch seems to address retro() or Result... John
Nov 03 2011
Here's my changes to it: //Convert a string representation of a type, produced by typeinfo into a .stringof representation string typeinfo2stringof(string id){ auto rid = retro(id); auto r1 = find(rid, '.'); auto rb = find(rid, '!'); auto r1len = r1.source.length; if(!rb.empty) { auto r1a = r1; r1a.popFront; rb.popFront; auto r2 = find(r1a,'.'); auto r1alen = r1a.source.length; auto r2len = r2.source.length; auto rblen = rb.source.length; assert(id[r2len..rblen]==id[r1len..r1len+ (rblen-r2len)], "Internal error in std.Variant regarding converting toString to stringof."); if(r1len+(rblen-r2len) >= id.length ) { id = id[r2len..r1alen]; } else { id = id[r2len..r1alen]~id[r1len +(rblen-r2len)..$]; } } else { id = id[r1len..$]; } return id; }
Nov 03 2011
And here's a working example: import std.stdio; import variant; import std.string; import std.conv; //---- class Base { private int y; //check if a variable causes any problems //run all member functions that start with "in" public void RunAllIn(alias T) () { writeln("RunAllIn: ", typeid(T)); Variant.__register!T; Variant var = this; foreach (i, m; __traits(derivedMembers, T)) { if (!startsWith(m, "in")) { continue; } writeln("== i=", i, " m=", m); var.__reflect(m); } } } //---- class Bob : Base { private int x; //check if a variable causes any problems //private int inx; //causes an exception this() { RunAllIn!Bob; } public void inBob1() { writeln(" in bob : inBob1()"); } public void inBob2() { writeln(" in bob : inBob2()"); } } //---- class Jane: Base { this() { RunAllIn!Jane; } public void inJane1() { writeln(" in jane : inJane1()"); } public void inJane2() { writeln(" in jane : inJane2()"); } } void main(string[] args) { new Bob(); new Jane(); } The output is: $ rm -f dtest; dmd dtest.d variant.d -ofdtest; ./dtest RunAllIn: dtest.Bob == i=2 m=inBob1 in bob : inBob1() == i=3 m=inBob2 in bob : inBob2() RunAllIn: dtest.Jane == i=1 m=inJane1 in jane : inJane1() == i=2 m=inJane2 in jane : inJane2() Perfect, thanks Robert! Works like a charm.
Nov 03 2011
On Tue, 01 Nov 2011 14:42:42 -0400, J Arrizza <cppgent0 gmail.com> wrote:Robert, I tried using variant.d using your exact test program below and I got compiler errors: $ dmd variant.d dtest.d variant.d(273): Error: no property 'length' for type 'Result' variant.d(273): Error: no property 'length' for type 'Result' variant.d(274): Error: no property 'length' for type 'Result' variant.d(274): Error: no property 'length' for type 'Result' variant.d(274): Error: no property 'length' for type 'Result' variant.d(275): Error: no property 'length' for type 'Result' variant.d(277): Error: no property 'length' for type 'Result' variant.d(277): Error: no property 'length' for type 'Result' variant.d(277): Error: no property 'length' for type 'Result' variant.d(277): Error: no property 'length' for type 'Result' variant.d(280): Error: no property 'length' for type 'Result' $ dmd -v DMD64 D Compiler v2.055 Am I missing a switch or something? JohnNope, (hopefully) just patches. I maintain a list of the bugzilla patches (i.e. http://d.puremagic.com/issues/show_bug.cgi?id=5155) I've applied at the top of the file. But, mostly those are so DMD doesn't ICE; I've never seen this particular error before and am not sure how to interpret it. Hmm.. I don't use a Result type, but std.algoroithm does and one of the patches I always use is 6256 (http://d.puremagic.com/issues/show_bug.cgi?id=6256), which addresses length for Map.
Nov 07 2011
On 2011-10-18 18:48, J Arrizza wrote:I'm trying to write some sample code to: 1 create an object via it's name 2 search an object for it's functions 3 call a static function in a class 4 call a non-static function in an object in DMD 2.0. I found this: http://www.digitalmars.com/d/archives/digitalmars/D/announce/Runtime_reflection_9949.html 64-bit Ubuntu. Any other avenues I can chase? TIA, JohnHow about doing something like this: class Foo { void bar () { writeln("bar"); } } void main () { auto foo = new Foo; auto members = __traits(derivedMembers, Foo); void delegate () dg; foreach (i, m ; members) if (m == "bar") dg.funcptr = cast(void function()) foo.classinfo.vtbl[i + 6]; dg.ptr = cast(void*) foo; dg(); } -- /Jacob Carlborg
Oct 19 2011
Just noticed an odd thing when I was trying Jacob's code. This works great: auto x = new someClass(); Object o = x; void delegate() dg; foreach(i, m; __traits(derivedMembers, someClass)) { writeln("i=", i, " m=", m); if(m != "__ctor") { dg.funcptr = cast(void function()) o.classinfo.vtbl[i + 6]; dg.ptr = cast(void*) o; dg(); } } but this doesn't (it segfaults): Object o = Object.factory("someClass"); void delegate() dg; foreach(i, m; __traits(derivedMembers, someClass)) { writeln("i=", i, " m=", m); if(m != "__ctor") { dg.funcptr = cast(void function()) o.classinfo.vtbl[i + 6]; dg.ptr = cast(void*) o; dg(); } } Is the object returned by Object.factory() not the same somehow as the one returned by new()? John
Oct 19 2011
On 2011-10-19 11:24, J Arrizza wrote:Just noticed an odd thing when I was trying Jacob's code. This works great: auto x = new someClass(); Object o = x; void delegate() dg; foreach(i, m; __traits(derivedMembers, someClass)) { writeln("i=", i, " m=", m); if(m != "__ctor") { dg.funcptr = cast(void function()) o.classinfo.vtbl[i + 6]; dg.ptr = cast(void*) o; dg(); } } but this doesn't (it segfaults): Object o = Object.factory("someClass"); void delegate() dg; foreach(i, m; __traits(derivedMembers, someClass)) { writeln("i=", i, " m=", m); if(m != "__ctor") { dg.funcptr = cast(void function()) o.classinfo.vtbl[i + 6]; dg.ptr = cast(void*) o; dg(); } } Is the object returned by Object.factory() not the same somehow as the one returned by new()? JohnFor Object.factory you need the fully qualified name, i.e. SomeClass.classinfo.name. If Object.factory can't find a class name it will just return null. -- /Jacob Carlborg
Oct 19 2011
Yup, didn't check for null, damn it. Can I blame it on working on it at 2:30AM? Forget the excuse, I just didn't check for null. For future reference, the fully qualified name for SomeClass is "SomeClass.SomeClass". If I create class Bob in the SomeClass file "SomeClass.Bob". The first node is the file name, the second the actual name of the class. I imagine there is additional complications for nested classes. Thanks Jacob, John For Object.factory you need the fully qualified name, i.e.SomeClass.classinfo.name. If Object.factory can't find a class name it will just return null. -- /Jacob Carlborg
Oct 19 2011
On 2011-10-20 07:44, J Arrizza wrote:Yup, didn't check for null, damn it. Can I blame it on working on it at 2:30AM? Forget the excuse, I just didn't check for null. For future reference, the fully qualified name for SomeClass is "SomeClass.SomeClass". If I create class Bob in the SomeClass file "SomeClass.Bob". The first node is the file name, the second the actual name of the class. I imagine there is additional complications for nested classes.The fully qualified class name includes the module the class is defined in, if you're unsure you can get it by running: writeln(SomeClass.classinfo.name);Thanks Jacob, John For Object.factory you need the fully qualified name, i.e. SomeClass.classinfo.name <http://SomeClass.classinfo.name>. If Object.factory can't find a class name it will just return null. -- /Jacob Carlborg-- /Jacob Carlborg
Oct 19 2011
On 2011-10-18 18:48, J Arrizza wrote:I'm trying to write some sample code to: 1 create an object via it's name 2 search an object for it's functions 3 call a static function in a class 4 call a non-static function in an object in DMD 2.0. I found this: http://www.digitalmars.com/d/archives/digitalmars/D/announce/Runtime_reflection_9949.html 64-bit Ubuntu. Any other avenues I can chase? TIA, JohnRuntime reflection by inspecting the symbol table of the currently executing application: http://flectioned.kuehne.cn/ -- /Jacob Carlborg
Oct 19 2011
Jacob, by the way, I did try flectioned and unfortunately it failed to compile. http://flectioned.kuehne.cn/ According to the comments it should work in windows or linux and it should work with D1 and D2. However I got quite a few compiler errors using: $ dmd -v DMD64 D Compiler v2.055 I tried fixing as many as I could, but at this point in my D skills, it was beyond me. It looked promising though. I did something similar by parsing the PE format of Windows DLLs http://www.arrizza.com/unittesters/utx/utx.html . Kind of kludgy though. I had to de-mangle the names in the internal PE dictionary, making it wholly reliant on the microsoft compiler. But it worked... John On Wed, Oct 19, 2011 at 1:22 AM, Jacob Carlborg <doob me.com> wrote:Runtime reflection by inspecting the symbol table of the currently executing application: http://flectioned.kuehne.cn/ -- /Jacob Carlborg-- John blog: http://arrizza.blogspot.com/ web: http://www.arrizza.com/
Oct 23 2011