www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Generic Delegate

reply "Miguel Ferreira Simões" <Kobold netcabo.pt> writes:
Is there anyway of having a delegate collection of different types?
When I want to call one I have to cast it to the correct type (I can use 
TypeInfo to store information on return and arguments types).

For example:

class Bar {
   void f1() { }

   int f2(int arg) { return arg; }

   //generic delegate container

   GenericDelegate[] _generic;

}

Thanks,
Miguel Ferreira Simoes 
Jan 17 2005
next sibling parent reply "Miguel Ferreira Simões" <Kobold netcabo.pt> writes:
I found that I cannot convert delegate to void*.
Is there any special reason?
Or the reason is just... you shouldn't program type unsafe?

(Probably I am missing something. But I would like to have this feature.)

Thanks. 
Jan 17 2005
parent reply Ben Hinkle <Ben_member pathlink.com> writes:
In article <csg6g8$15k3$1 digitaldaemon.com>, Miguel Ferreira Simões says...
I found that I cannot convert delegate to void*.
Is there any special reason?
Or the reason is just... you shouldn't program type unsafe?

(Probably I am missing something. But I would like to have this feature.)

Thanks. 

A delegate stores 2 pointers: one to the object and one to the function. The object becomes "this" inside the function. So you can't cast it to void* since the sizes are different. -Ben
Jan 17 2005
parent reply "Miguel Ferreira Simões" <Kobold netcabo.pt> writes:
Thanks.
So it's impossible to have a generic delegate (pointer), isn't it?
Or is there any way to wrap all kind of possible delegates?

Miguel 
Jan 17 2005
parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
"Miguel Ferreira Simões" <Kobold netcabo.pt> wrote in message
news:csgj0h$1jq3$1 digitaldaemon.com...
 Thanks.
 So it's impossible to have a generic delegate (pointer), isn't it?
 Or is there any way to wrap all kind of possible delegates?

 Miguel

I'm not really sure what you mean by "generic". Your initial post didn't actually use the _generic member so I'm guessing at some point you add f1 and f2 to _generic. Maybe try something like import std.stdio; alias void delegate() GenericDelegate; alias int delegate(int arg) SpecificDelegate; class Bar { void f1() { writefln("in f1"); } int f2(int arg) { return arg; } //generic delegate container GenericDelegate[] _generic; } int main() { Bar x = new Bar; x._generic ~= &x.f1; x._generic ~= cast(GenericDelegate)&x.f2; x._generic[0](); SpecificDelegate y = cast(SpecificDelegate)x._generic[1]; writefln(y(123)); return 0; }
Jan 17 2005
parent "Miguel Ferreira Simões" <Kobold netcabo.pt> writes:
Thanks!!

That's what I need! 
Jan 17 2005
prev sibling next sibling parent Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Miguel Ferreira Simões wrote:
 Is there anyway of having a delegate collection of different types?
 When I want to call one I have to cast it to the correct type (I can use 
 TypeInfo to store information on return and arguments types).
 
 For example:
 
 class Bar {
    void f1() { }
 
    int f2(int arg) { return arg; }
 
    //generic delegate container
 
    GenericDelegate[] _generic;
 
 }

When you mix two delegates that have different argument lists, you have trouble because one is expecting an argument while another is not. If you call the one that expects arguments, and don't pass it one, something is going to go very wrong. Likewise if you pass an argument to a delegate which doesn't expect it. You can get around this by declaring a struct which stores both your delegate, and the argument you want to pass into it: struct DelegateArgumentRemover(Tret,Targ) { Tret delegate(Targ) original_delegate; Targ saved_argument; Tret opCall() { return original_delegate(saved_argument); } } template RemoveArgument(Tret,Targ) { Tret delegate() RemoveArgument(Tret delegate(Targ) delegate, Targ arg) { DelegateArgumentRemover!(Tret,Targ) *temp = new DelegateArgumentRemover!(Tret,Targ); temp.original_delegate = delegate; temp.saved_argument = arg; return &temp.opCall; } } void fn1() { ... }; void fn2(int arg) { ... }; void delegate()[] delegates; delegates.length = 2; delegates[0] = &fn1; delegates[1] = RemoveArgument!(void,int).RemoveArgument(&fn2, 1234);
Jan 17 2005
prev sibling parent reply "Miguel Ferreira Simões" <Kobold netcabo.pt> writes:
I'm getting despaired! :(

The problem is the following...
I am trying to write "method.forName" support.
Every callable method registers itself in the constructor.

Then I want to call a method with this syntax:
    methodRead(char[] name, ...)

methodRead should know the right arguments of the method (information must 
be stored during the registry process).

But I am not sure if this is possible in D... does anybody have a clue?

Thanks a lot!
Miguel 
Jan 17 2005
next sibling parent Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Miguel Ferreira Simões wrote:
 I'm getting despaired! :(
 
 The problem is the following...
 I am trying to write "method.forName" support.
 Every callable method registers itself in the constructor.
 
 Then I want to call a method with this syntax:
     methodRead(char[] name, ...)
 
 methodRead should know the right arguments of the method (information must 
 be stored during the registry process).
 
 But I am not sure if this is possible in D... does anybody have a clue?

In D (just like in C or C++), the *caller* of a varargs function must use a predefined number & type of arguments. You can't just construct a varargs on the fly. (Well, perhaps you could, if you knew enough about the internal design, but that's not very reliable or portable.) If you really want to pass arguments of varying types, perhaps you should define a wrapper type? You could pass an array of structs, where each struct represents an argument. Each struct has information that lets you determine both its type and its value.
Jan 17 2005
prev sibling parent "Ben Hinkle" <bhinkle mathworks.com> writes:
"Miguel Ferreira Simões" <Kobold netcabo.pt> wrote in message
news:csgn22$1ops$1 digitaldaemon.com...
 I'm getting despaired! :(

 The problem is the following...
 I am trying to write "method.forName" support.
 Every callable method registers itself in the constructor.

 Then I want to call a method with this syntax:
     methodRead(char[] name, ...)

 methodRead should know the right arguments of the method (information must
 be stored during the registry process).

 But I am not sure if this is possible in D... does anybody have a clue?

 Thanks a lot!
 Miguel

You might want to check out std.loader which gives an API for looking up symbols from executable and shared libraries. You'll have to do the name mangling by hand, I think since the loader code just hands the symbol name to the OS to look up and it doesn't have any idea about D's name mangling. Once you get a pointer to the function you'll have to cook up the stack - also not trivial as Russ points out. Basically, D doesn't have an reflection API.
Jan 17 2005