Thread overview
Get specific functions of unknown type at runtime?
Dec 17, 2012
F i L
Dec 17, 2012
Adam D. Ruppe
Dec 17, 2012
F i L
Dec 17, 2012
Jacob Carlborg
Dec 17, 2012
Adam D. Ruppe
Dec 18, 2012
F i L
Dec 17, 2012
Jacob Carlborg
December 17, 2012
My goal is this, to have an XML file:

    <!-- scene.xml -->
    <scene>
        <object class="Person" event="greet"/>
    </scene>

and a D file:

    module person;

    import std.stdio;

    class Person
    {
        void greet() {
            writeln("hello");
        }
    }

and then another D file:

    module main;

    import person;
    import std.xml;
    import std.file;

    static class Engine
    {
        static void delegate() event;
        static void callEvent() { event(); }
    }

    void main() {
        auto doc = new Document(read("scene.xml"));
        auto className = /* find class name in xml file */;
        auto eventName = /* find event name in xml file */;
        auto obj = Object.factory(className);

        Engine.event = /* get 'eventName' void in 'obj' */;

        for (/* some loop */) { Engine.callEvent(); }
    }

So yeah, basically is is possible to create a general object, then look at it's members at runtime? Through maybe a .classinfo or something? Or is this level of runtime reflection simply not supported in D (yet)? If so, what are my best alternative options here?
December 17, 2012
The way I'd do it is to make an interface with a generic call method. The classes themselves fill this out using __traits.


interface SceneObject {
       void _callFunction(string name);
}

mixin template SceneObjectReflection() {
     override void _callFunction(string name) {
           foreach(funcname; __traits(derivedMembers, typeof(this))) {
                static if(funcname[0] != '_') // just to skip stuff like _ctor
                if(funcname == name) {
                    __traits(getMember, this, funcname)();
                    return;
                }
           }
           throw new Exception("no such method");
     }
}

class Person : SceneObject {
    mixin SceneObjectReflection!();
    void greet() { writeln("hello"); }
}




Then you can use it like:

void main() {
   auto obj = cast(SceneObject) Object.factory("test6.Person") ;
   if(obj is null) throw new Exception("no such class");
   obj._callFunction("greet");
}



Where of course the class name and the function name are runtime strings.


It will still be a bumpy ride to make this work in a real world situation, but this is how I would get started.
December 17, 2012
On 2012-12-17 02:39, F i L wrote:
> My goal is this, to have an XML file:
>
>      <!-- scene.xml -->
>      <scene>
>          <object class="Person" event="greet"/>
>      </scene>
>
> and a D file:
>
>      module person;
>
>      import std.stdio;
>
>      class Person
>      {
>          void greet() {
>              writeln("hello");
>          }
>      }
>
> and then another D file:
>
>      module main;
>
>      import person;
>      import std.xml;
>      import std.file;
>
>      static class Engine
>      {
>          static void delegate() event;
>          static void callEvent() { event(); }
>      }
>
>      void main() {
>          auto doc = new Document(read("scene.xml"));
>          auto className = /* find class name in xml file */;
>          auto eventName = /* find event name in xml file */;
>          auto obj = Object.factory(className);
>
>          Engine.event = /* get 'eventName' void in 'obj' */;
>
>          for (/* some loop */) { Engine.callEvent(); }
>      }
>
> So yeah, basically is is possible to create a general object, then look
> at it's members at runtime? Through maybe a .classinfo or something? Or
> is this level of runtime reflection simply not supported in D (yet)? If
> so, what are my best alternative options here?

For the serialization part you could have a look at Orange:

https://github.com/jacob-carlborg/orange

It won't handle the dynamic methods though.

-- 
/Jacob Carlborg
December 17, 2012
@Adam D. Ruppe

Damn, I was afraid you where going to say to do something like that. It doesn't really work for what I'm thinking about, but thanks for confirming that my original code can't work.

I have an alternative in mind, but first, is there a possible way for a Super class to ask about a derivative's members during constructions? (I'm guessing not). Something like:

    import std.stdio, std.traits;

    class A
    {
        this() {
            alias typeof(this) type;
            static if (hasMember!(type, "foo")) {
                auto top = cast(type) this;
                top.foo();
            }
        }
    }

    class B : A
    {
        void foo() { writeln("foobar"); }
    }

    void main() {
        auto b = new B(); // prints: 'foobar'
    }

I assume there's no way (I can't get it to work), but I've heard odd things about 'typeof(this)' before, I just can't remember exactly what, so I figure it's worth asking about.

If not, I have an alternative way to accomplish what I want. It's just not as ideal. I really wish D has partial classes, that would be awesome.




@Jacob Carlborg

Thanks for the link.
December 17, 2012
On 2012-12-17 08:54, F i L wrote:
> @Adam D. Ruppe
>
> Damn, I was afraid you where going to say to do something like that. It
> doesn't really work for what I'm thinking about, but thanks for
> confirming that my original code can't work.
>
> I have an alternative in mind, but first, is there a possible way for a
> Super class to ask about a derivative's members during constructions?
> (I'm guessing not). Something like:
>
>      import std.stdio, std.traits;
>
>      class A
>      {
>          this() {
>              alias typeof(this) type;
>              static if (hasMember!(type, "foo")) {
>                  auto top = cast(type) this;
>                  top.foo();
>              }
>          }
>      }
>
>      class B : A
>      {
>          void foo() { writeln("foobar"); }
>      }
>
>      void main() {
>          auto b = new B(); // prints: 'foobar'
>      }
>
> I assume there's no way (I can't get it to work), but I've heard odd
> things about 'typeof(this)' before, I just can't remember exactly what,
> so I figure it's worth asking about.
>
> If not, I have an alternative way to accomplish what I want. It's just
> not as ideal. I really wish D has partial classes, that would be awesome.

Don't know if this is what you need, but you could talk a look at:

http://flectioned.kuehne.cn/

It's basically runtime reflection implemented by inspecting the symbol table in the currently running executable. Note that this is old D1 code.

-- 
/Jacob Carlborg
December 17, 2012
On Monday, 17 December 2012 at 07:54:08 UTC, F i L wrote:
> I have an alternative in mind, but first, is there a possible way for a Super class to ask about a derivative's members during constructions? (I'm guessing not). Something like:

Not that I know of, no. Though maybe a templated constructor could so some magic.

class SceneObject {
   this(T)(T t) { ... }
}

class Person : SceneObject {
    this() { super(this); } // calls the templated superclass magic, which will have T == Person
}

But this isn't that much different than the mixin approach in that you still have to do something special with the child classes.


My dmd segfaults when I don't put a constructor in the child class at all... I think there's bug fixes coming in the new dmd about these templated constructors so it might get better. idk.
December 18, 2012
Okay, thanks for the help folks.