www.digitalmars.com         C & C++   DMDScript  

D - new D site

reply "Pavel Minayev" <evilone omen.ru> writes:
My old tiny D page had grown into the site! You can still get all
the stuff I've made, there, but there's also my D FAQ, and some
information on my D projects, including not-yet-released WinD.

Unfortunately, Russ is unable to provide hosting further, for
several reasons, so the site has moved to my ex-homepage,
http://int19h.tamb.ru. You can still access it via the old URL,
though - it'll redirect you there.
Mar 30 2002
next sibling parent "Walter" <walter digitalmars.com> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:a86b4p$1elj$1 digitaldaemon.com...
 My old tiny D page had grown into the site! You can still get all
 the stuff I've made, there, but there's also my D FAQ, and some
 information on my D projects, including not-yet-released WinD.

 Unfortunately, Russ is unable to provide hosting further, for
 several reasons, so the site has moved to my ex-homepage,
 http://int19h.tamb.ru. You can still access it via the old URL,
 though - it'll redirect you there.

Thanks! It's a cool web site. -Walter
Mar 31 2002
prev sibling next sibling parent reply "OddesE" <OddesE_XYZ hotmail.com> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:a86b4p$1elj$1 digitaldaemon.com...
 My old tiny D page had grown into the site! You can still get all
 the stuff I've made, there, but there's also my D FAQ, and some
 information on my D projects, including not-yet-released WinD.

 Unfortunately, Russ is unable to provide hosting further, for
 several reasons, so the site has moved to my ex-homepage,
 http://int19h.tamb.ru. You can still access it via the old URL,
 though - it'll redirect you there.

Wow Pavel, it looks great! I liked the code example from WinD! So it seems you have decided on the event handling? You seem to be using a function pointer in combination with an object pointer? -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net _________________________________________________ Remove _XYZ from my address when replying by mail
Mar 31 2002
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"OddesE" <OddesE_XYZ hotmail.com> wrote in message
news:a8868m$2d6u$1 digitaldaemon.com...

 Wow Pavel, it looks great!
 I liked the code example from WinD!
 So it seems you have decided on the event handling?
 You seem to be using a function pointer in
 combination with an object pointer?

Yes, it seems to be the best way for now!
Mar 31 2002
parent reply "J. Daniel Smith" <j_daniel_smith HoTMaiL.com> writes:
This looks a lot like C#'s "delegates and events" mechanism.  Coincidence?
Is it worth making this technique a standard part of the language like C#?

   Dan

"Pavel Minayev" <evilone omen.ru> wrote in message
news:a88uv7$2q1e$1 digitaldaemon.com...
 "OddesE" <OddesE_XYZ hotmail.com> wrote in message
 news:a8868m$2d6u$1 digitaldaemon.com...

 Wow Pavel, it looks great!
 I liked the code example from WinD!
 So it seems you have decided on the event handling?
 You seem to be using a function pointer in
 combination with an object pointer?

Yes, it seems to be the best way for now!

Apr 01 2002
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"J. Daniel Smith" <j_daniel_smith HoTMaiL.com> wrote in message
news:a89tgs$bmi$1 digitaldaemon.com...

 This looks a lot like C#'s "delegates and events" mechanism.  Coincidence?
 Is it worth making this technique a standard part of the language like C#?

I proposed it a hundred times already! Probably, I wasn't that convincing... =)
Apr 01 2002
parent reply "Walter" <walter digitalmars.com> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:a8a89q$hd7$1 digitaldaemon.com...
 "J. Daniel Smith" <j_daniel_smith HoTMaiL.com> wrote in message
 news:a89tgs$bmi$1 digitaldaemon.com...
 This looks a lot like C#'s "delegates and events" mechanism.


 Is it worth making this technique a standard part of the language like


 I proposed it a hundred times already!
 Probably, I wasn't that convincing... =)

The problem is I don't understand the problem. I've been buried with work lately, and haven't given that issue the attention it needs. -Walter
Apr 01 2002
next sibling parent "J. Daniel Smith" <j_daniel_smith HoTMaiL.com> writes:
Essentially, C#'s delegates are a way to easily maintain a collection of
(member-) function pointers; firing an event invokes each of the function
pointers.  With a bit of work, you can achieve similar functionality in C++,
although you need templates (and ideally partial template specialization)
for type-safety.  Building the feature directly into the language makes the
syntax a lot easier (and neither C# or D have templates making it harder to
"roll your own").

   Dan

"Walter" <walter digitalmars.com> wrote in message
news:a8ad5n$r5c$1 digitaldaemon.com...
 "Pavel Minayev" <evilone omen.ru> wrote in message
 news:a8a89q$hd7$1 digitaldaemon.com...
 "J. Daniel Smith" <j_daniel_smith HoTMaiL.com> wrote in message
 news:a89tgs$bmi$1 digitaldaemon.com...
 This looks a lot like C#'s "delegates and events" mechanism.


 Is it worth making this technique a standard part of the language like


 I proposed it a hundred times already!
 Probably, I wasn't that convincing... =)

The problem is I don't understand the problem. I've been buried with work lately, and haven't given that issue the attention it needs. -Walter

Apr 01 2002
prev sibling parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Walter" <walter digitalmars.com> wrote in message
news:a8ad5n$r5c$1 digitaldaemon.com...

 The problem is I don't understand the problem. I've been buried with work
 lately, and haven't given that issue the attention it needs. -Walter

First of all, an example: class Button { event void onMouseMove(int, int); // event (pointer to function) ... void mouseMoved(int x, int y) { // raise event (will first call OK_MouseMove1, then OK_MouseMove2) onMouseMove(x, y); } } void OK_MouseMove1(int x, int y) // global event handler { ... } class MyForm: Form { Button OK; void OK_MouseMove2(int x, int y) // local event handler { ... } this() { OK.onMouseMove = OK_MouseMove1; // set event handler OK.onMouseMove ~= OK_MouseMove2; // add another handler } } Advantage of this approach is that you can make global, static, and nonstatic member functions event handlers - unlike usual function pointers, which only allow global and static functions. In most cases, event handler is actually part of the class, and now, to make it work, it needs to be declared static, and to get "this" pointer as one of explicit arguments: static void OK_MouseMove(Object self, int x, int y) { ... } Not only this requires typing "self.blablabla" all the time (or wrap the function into with-block), but you also have to cast self to whatever class it actually is...
Apr 01 2002
next sibling parent "Pavel Minayev" <evilone omen.ru> writes:
Also, note that several handlers may be attached to a single
event slot. Practically, it's an array of pointers, not a
single pointer, and functions are called in straight order:

    event void onInit();
    void foo();
    void bar();
    void baz();

    onInit = &foo;             // set
    onInit = &onInit ~ &bar;   // add another
    onInit ~= &baz;            // one more
    onInit = onInit[0 .. 1] ~  // remove bar()
        onInit[2 .. 3];

    onInit();    // call foo(), then baz()
Apr 01 2002
prev sibling next sibling parent reply Jan Jezabek <jezabek poczta.onet.pl> writes:
I think that pointers to member functions (which as far as I know aren't 
there in D) should be explicitly castable to a normal function pointer, 
for example:

   class one
   {
     public:
       int x(int y);
   };

   typedef int (*FPTR)(void *, int);

   void main()
   {
     FPTR z = (FPTR) &one::x; // this will give an error
     one instance;

     z(&instance, 10); // same as instance->x
   }

If such cast was legal, it would solve your problem (of course I might 
be wrong:). Of course it's quite inconvenient, and I would prefer using 
delegates just as I preferred virtual functions over function pointers.

 Advantage of this approach is that you can make global, static, and
 nonstatic
 member functions event handlers - unlike usual function pointers, which
 only allow global and static functions. In most cases, event handler is
 actually part of the class, and now, to make it work, it needs to be
 declared static, and to get "this" pointer as one of explicit arguments:
 
     static void OK_MouseMove(Object self, int x, int y)
     {
         ...
     }
 
 Not only this requires typing "self.blablabla" all the time (or wrap the
 function into with-block), but you also have to cast self to whatever
 class it actually is...

Apr 02 2002
next sibling parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Jan Jezabek" <jezabek poczta.onet.pl> wrote in message
news:3CA9DC00.4070601 poczta.onet.pl...

 I think that pointers to member functions (which as far as I know aren't
 there in D) should be explicitly castable to a normal function pointer,
 for example:

    class one
    {
      public:
        int x(int y);
    };

    typedef int (*FPTR)(void *, int);

    void main()
    {
      FPTR z = (FPTR) &one::x; // this will give an error
      one instance;

      z(&instance, 10); // same as instance->x
    }

Don't forget that there is no fixed calling convention in D, functions might get called in a way different from methods, so this is not guaranteed to work...
Apr 02 2002
parent Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Pavel Minayev wrote:

 "Jan Jezabek" <jezabek poczta.onet.pl> wrote in message
 news:3CA9DC00.4070601 poczta.onet.pl...

 Don't forget that there is no fixed calling convention in D,
 functions might get called in a way different from methods,
 so this is not guaranteed to work...

Function pointers need to specify the calling conventions, then...including, perhaps a "D-member-function" calling convention. -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Apr 02 2002
prev sibling parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
There are two key types of member function pointers; if D supports member
function pointers, it should support both:

    * Pointers that include a pointer to the object they are to be called on.
These are useful for event handlers and such, where you know which object
should handle the event.
    * Pointers that do NOT include an object pointer.  These are useful where
you might have a class (perhaps a child class) register the handler to use on
ANY of its objects when a certain event occurs.

I don't know what a good syntax for the two types might be.

--
The Villagers are Online! villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]
Apr 02 2002
next sibling parent reply Jan Jezabek <jezabek poczta.onet.pl> writes:
Isn't it the same as pointers to static member functions (I might be 
getting something wrong)?

Russ Lewis wrote:
     * Pointers that do NOT include an object pointer.  These are useful where
 you might have a class (perhaps a child class) register the handler to use on
 ANY of its objects when a certain event occurs.

Apr 02 2002
next sibling parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Jan Jezabek wrote:

 Isn't it the same as pointers to static member functions (I might be
 getting something wrong)?

 Russ Lewis wrote:
     * Pointers that do NOT include an object pointer.  These are useful where
 you might have a class (perhaps a child class) register the handler to use on
 ANY of its objects when a certain event occurs.


I'm thinking more along the lines of things that might be registered for a class of objects, but when called should be called as member objects, not static. This would work when you have a group of related objects, and you want to save a single function pointer that is the handler for a particular event for ALL of those objects. Also, I think that member function pointers should properly handle virtual calls. That is, you can save a pointer to a virtual function (remember, all member functions in D are virtual automatically), and the code will, at runtime, call the right virtual version of it. This probably would require the compiler to create wrapper functions in some circumstances :( -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Apr 02 2002
next sibling parent Jan Jezabek <jezabek poczta.onet.pl> writes:
Russ Lewis wrote:
 I'm thinking more along the lines of things that might be registered for a
class of
 objects, but when called should be called as member objects, not static.  This
 would work when you have a group of related objects, and you want to save a
single
 function pointer that is the handler for a particular event for ALL of those
 objects.

Something like a static pointer to a non-static member function? :) I think it's already there in C++. I have no experience in C# so I don't know if there are static delegates.
 Also, I think that member function pointers should properly handle virtual
calls.
 That is, you can save a pointer to a virtual function (remember, all member
 functions in D are virtual automatically), and the code will, at runtime, call
the
 right virtual version of it.  This probably would require the compiler to
create
 wrapper functions in some circumstances :(

I think it is easier than having mixed virtual and non-virtual functions. Consider the following example: #include <stdio.h> class base { public: int a() { printf("base\n"); } virtual int b() { printf("base\n"); } }; class derived: public base { public: int a() { printf("derived\n"); } virtual int b() { printf("derived\n"); } }; int main() { int (base::*ptr)(); base X; derived Y; ptr = &base::a; // non-virtual (X.*ptr)(); // prints "base" (Y.*ptr)(); // prints "base" ptr = &base::b; // virtual (X.*ptr)(); // prints "base" (Y.*ptr)(); // prints "derived" return 0; } How does the code know whether to call a virtual or a non-virtual function?
Apr 02 2002
prev sibling next sibling parent "Pavel Minayev" <evilone omen.ru> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3CA9E742.B2C0766E deming-os.org...

 Also, I think that member function pointers should properly handle virtual

 That is, you can save a pointer to a virtual function (remember, all

 functions in D are virtual automatically), and the code will, at runtime,

 right virtual version of it.  This probably would require the compiler to

 wrapper functions in some circumstances :(

You probably mean for the second type of pointers (to class members rather than to object members)? Once again, I don't think these are of real importance, for now at least. Delegates are, on one hand, more useful, and on other, seem to be simpler to implement (so we can hope to convince Walter to do it relatively easy =)).
Apr 02 2002
prev sibling parent reply "Richard Krehbiel" <rich kastle.com> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3CA9E742.B2C0766E deming-os.org...
 Also, I think that member function pointers should properly handle virtual

 That is, you can save a pointer to a virtual function (remember, all

 functions in D are virtual automatically), and the code will, at runtime,

 right virtual version of it.  This probably would require the compiler to

 wrapper functions in some circumstances :(

So, an object should be able to change type during it's lifetime? That's not an operation that's supported in any OO-language that I know of - absent ugly unsupported pointer-poking hacks. It wasn't too many message ago I was reading how Walter was messing with the vtbl in his platform/compiler-specific code - for shame, Walter! :-) Even so, it supportable by having a method pointer be {object pointer, vtbl offset}, rather than {function pointer, object pointer}. Not really a big deal when all methods are virtual; problematic when many are not (as in C++). -- Richard Krehbiel, Arlington, VA, USA rich kastle.com (work) or krehbiel3 comcast.net (personal)
Apr 02 2002
next sibling parent "Pavel Minayev" <evilone omen.ru> writes:
"Richard Krehbiel" <rich kastle.com> wrote in message
news:a8d3jm$2ejp$1 digitaldaemon.com...

 ugly unsupported pointer-poking hacks.  It wasn't too many message ago I

 reading how Walter was messing with the vtbl in his
 platform/compiler-specific code - for shame, Walter!  :-)

Well, actually, it was me messing with the vtbl =)
 Even so, it supportable by having a method pointer be {object pointer,

 offset}, rather than {function pointer, object pointer}.  Not really a big
 deal when all methods are virtual; problematic when many are not (as in

Don't see any reason in it; why store the offset, if the value there is constant and doesn't change as program runs? Isn't it simplier AND faster to store the pointer itself, especially since not all methods are virtual (compiler decides).
Apr 02 2002
prev sibling next sibling parent Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Richard Krehbiel wrote:

 So, an object should be able to change type during it's lifetime?  That's
 not an operation that's supported in any OO-language that I know of - absent
 ugly unsupported pointer-poking hacks.  It wasn't too many message ago I was
 reading how Walter was messing with the vtbl in his
 platform/compiler-specific code - for shame, Walter!  :-)

Guess I wasn't clear. :) I meant this only for member function pointers that did NOT include the object pointer. That is, you attach the pointer at one time and at a later date use it against some object(s). The pointer, in this case, would use the appropriate virtual function for the object it was run against. However, if we only support pointers to static members and pointers to members WITH the object pointer, then you're right, this point is moot. -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Apr 02 2002
prev sibling parent "Walter" <walter digitalmars.com> writes:
"Richard Krehbiel" <rich kastle.com> wrote in message
news:a8d3jm$2ejp$1 digitaldaemon.com...
 So, an object should be able to change type during it's lifetime?  That's
 not an operation that's supported in any OO-language that I know of -

 ugly unsupported pointer-poking hacks.  It wasn't too many message ago I

 reading how Walter was messing with the vtbl in his
 platform/compiler-specific code - for shame, Walter!  :-)

All's fair when trying to win benchmarks!
Apr 02 2002
prev sibling parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Jan Jezabek" <jezabek poczta.onet.pl> wrote in message
news:3CA9E3ED.3060600 poczta.onet.pl...

 Isn't it the same as pointers to static member functions (I might be
 getting something wrong)?

It is the same type of pointers you could see in C++: class Foo; void (Foo::*ptr)(); // pointer to member of Foo Foo foo; foo->*ptr(); // call it I don't really see much need in it, however. In my experience (not so long, but still...), I've never ever used C++ pointers to members. Can anyone give a sample where these might be useful?
Apr 02 2002
parent "Sean L. Palmer" <spalmer iname.com> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:a8ct54$2aja$1 digitaldaemon.com...
 "Jan Jezabek" <jezabek poczta.onet.pl> wrote in message
 news:3CA9E3ED.3060600 poczta.onet.pl...

 Isn't it the same as pointers to static member functions (I might be
 getting something wrong)?

It is the same type of pointers you could see in C++: class Foo; void (Foo::*ptr)(); // pointer to member of Foo Foo foo; foo->*ptr(); // call it I don't really see much need in it, however. In my experience (not so

 but still...), I've never ever used C++ pointers to members. Can anyone
 give a sample where these might be useful?

They're good for implementing some kinds of state machines... usually the object pointer is something simple, such as "this" or "objectwithmethodtocall". Other people may have found some more exotic uses for it. Sean
Apr 04 2002
prev sibling parent reply Russell Borogove <kaleja estarcion.com> writes:
Russ Lewis wrote:
 There are two key types of member function pointers; if D supports member
 function pointers, it should support both:
 
     * Pointers that include a pointer to the object they are to be called on.
 These are useful for event handlers and such, where you know which object
 should handle the event.
     * Pointers that do NOT include an object pointer.  These are useful where
 you might have a class (perhaps a child class) register the handler to use on
 ANY of its objects when a certain event occurs.
 
 I don't know what a good syntax for the two types might be.

I'm not sure I understand -- normally, wouldn't the target-object pointer be part of the call, rather than part of the function pointer? -Russell B
Apr 02 2002
next sibling parent Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Russell Borogove wrote:

 I'm not sure I understand -- normally, wouldn't the target-object
 pointer be part of the call, rather than part of the function
 pointer?

Let's use Pavel's example. We have created a button object, which has some standard behavior. Then we create a form that includes that button. When the button is pressed, we want a specific function in the form to be called. Thus, we have a function pointer in the Button object, which we set to point at the form object. When the button is pressed, this function is called. Now, it makes no sense in this example to have a "generic" function pointer that can be called on any object...we only want the call to go to one specific Form object. Thus, if you don't include the pointer to the Form in the function pointer, then you have to have a 2nd variable in the Button that stores the pointer to the Form. Worse, you have to remember that this Button is a standard object which could be included in many things...Forms, dialogs, message boxes, etc. So we can't actually store a pointer to type Form there...instead, we have to store a pointer to Object, since it could point to any type of object. But will the function pointer syntax allow you to call a member function pointer to Form when all you have is a pointer to an Object? Anyhow, what I'm saying is that in some circumstances, it doesn't make any sense to separate the function pointer from the object it is intended to be called with. -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Apr 02 2002
prev sibling parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Russell Borogove" <kaleja estarcion.com> wrote in message
news:3CA9E738.30607 estarcion.com...

 I'm not sure I understand -- normally, wouldn't the target-object
 pointer be part of the call, rather than part of the function
 pointer?

No. Delegate variable stores both pointer to object and to method, and it doesn't care about object's class at all. When you call the pointer, it passes the object to the function as if it was "this". As the result, pointers to member functions behave in the same way as pointers to static functions - you won't see any difference. It would be even better if, like in C#, delegates would be able to hold pointers to static functions as well (when pointer to object == null), and be able to call both types properly.
Apr 02 2002
parent reply "J. Daniel Smith" <j_daniel_smith HoTMaiL.com> writes:
Content-Type: text/plain;
	charset="Windows-1252"
Content-Transfer-Encoding: quoted-printable

Here's some C++ code snippets to demonstrate how delegates/events work =
in C#.  Note that C# borrows heavily for Java: there are no global =
functions, everything is in some class.

=20

   Dan

=20

class DelegatesAndEvents

{

            // C#: public delegate void PrintString(string s);

            typedef DelegateT<Object::void1_T<string>::mf_t, string> =
PrintString_;

public:

            template <typename OBJECT>

                        static PrintString_ PrintString(OBJECT& o, void =
(OBJECT::*mf)(string)) {

                        return PrintString_(o, =
static_cast<Object::void1_T<string>::mf_t>(mf));

            }

            // C#: public event PrintString MyPrintString;

            PrintString_::Event MyPrintString;         =20

=20

            void FirePrintString(string s) {

                        MyPrintString(s);

            }

};

=20

class MyDelegates : public ObjectT<MyDelegates>

{

private:

            string m_name;

public:

            void SimpleDelegateFunction(string s)

            {

                        printf("SimpleDelegateFunction called from %s, =
string=3D%s\n", m_name, s);

            }

};

=20

void main()

{

DelegatesAndEvents dae;

            MyDelegates d;

=20

            dae.MyPrintString +=3D DelegatesAndEvents::PrintString(d, =
&MyDelegates::SimpleDelegateFunction);

=20

            dae.FirePrintString("Event fired!");

}

=20
Apr 02 2002
parent "Pavel Minayev" <evilone omen.ru> writes:
Content-Type: text/plain;
	charset="Windows-1252"
Content-Transfer-Encoding: quoted-printable


  "J. Daniel Smith" <j_daniel_smith HoTMaiL.com> wrote in message =
news:a8d5d1$2fic$1 digitaldaemon.com...
  Here's some C++ code snippets to demonstrate how delegates/events work =
in C#.  Note that C# borrows heavily for Java: there are no global =
functions, everything is in some class.



But C# allows static member functions (which are essentially the same as =
globals) to be used as delegates.
Apr 02 2002
prev sibling parent reply "Walter" <walter digitalmars.com> writes:
So, "event" consists of both an object pointer and a virtual function? Is
the event an array of these, called sequentially, or only the "top of stack"
last entry is called?

"Pavel Minayev" <evilone omen.ru> wrote in message
news:a8afmg$sb6$1 digitaldaemon.com...
 "Walter" <walter digitalmars.com> wrote in message
 news:a8ad5n$r5c$1 digitaldaemon.com...

 The problem is I don't understand the problem. I've been buried with


 lately, and haven't given that issue the attention it needs. -Walter

First of all, an example: class Button { event void onMouseMove(int, int); // event (pointer to

         ...
         void mouseMoved(int x, int y)
         {
             // raise event (will first call OK_MouseMove1, then
 OK_MouseMove2)
             onMouseMove(x, y);
         }
     }

     void OK_MouseMove1(int x, int y)    // global event handler
     {
         ...
     }

     class MyForm: Form
     {
         Button OK;

         void OK_MouseMove2(int x, int y)    // local event handler
         {
             ...
         }

         this()
         {
             OK.onMouseMove = OK_MouseMove1;    // set event handler
             OK.onMouseMove ~= OK_MouseMove2;   // add another handler
         }

     }

 Advantage of this approach is that you can make global, static, and
 nonstatic
 member functions event handlers - unlike usual function pointers, which
 only allow global and static functions. In most cases, event handler is
 actually part of the class, and now, to make it work, it needs to be
 declared static, and to get "this" pointer as one of explicit arguments:

     static void OK_MouseMove(Object self, int x, int y)
     {
         ...
     }

 Not only this requires typing "self.blablabla" all the time (or wrap the
 function into with-block), but you also have to cast self to whatever
 class it actually is...

Apr 02 2002
parent reply "J. Daniel Smith" <j_daniel_smith HoTMaiL.com> writes:
In C# (actually, the .NET framework), an object pointer and a pointer to one
of its member functions are wrapped up into a single object called a
"Delegate", the C# "delegate" keyword makes it easy to create a Delegate
object.  An Event object is a collection of delegates; the collection itself
is a "set" because 1) a calling order is not defined and 2) adding the same
delegate twice does not result in two calls.

   Dan

"Walter" <walter digitalmars.com> wrote in message
news:a8corb$28g2$1 digitaldaemon.com...
 So, "event" consists of both an object pointer and a virtual function? Is
 the event an array of these, called sequentially, or only the "top of

 last entry is called?

 "Pavel Minayev" <evilone omen.ru> wrote in message
 news:a8afmg$sb6$1 digitaldaemon.com...
 "Walter" <walter digitalmars.com> wrote in message
 news:a8ad5n$r5c$1 digitaldaemon.com...

 The problem is I don't understand the problem. I've been buried with


 lately, and haven't given that issue the attention it needs. -Walter

First of all, an example: class Button { event void onMouseMove(int, int); // event (pointer to

         ...
         void mouseMoved(int x, int y)
         {
             // raise event (will first call OK_MouseMove1, then
 OK_MouseMove2)
             onMouseMove(x, y);
         }
     }

     void OK_MouseMove1(int x, int y)    // global event handler
     {
         ...
     }

     class MyForm: Form
     {
         Button OK;

         void OK_MouseMove2(int x, int y)    // local event handler
         {
             ...
         }

         this()
         {
             OK.onMouseMove = OK_MouseMove1;    // set event handler
             OK.onMouseMove ~= OK_MouseMove2;   // add another handler
         }

     }

 Advantage of this approach is that you can make global, static, and
 nonstatic
 member functions event handlers - unlike usual function pointers, which
 only allow global and static functions. In most cases, event handler is
 actually part of the class, and now, to make it work, it needs to be
 declared static, and to get "this" pointer as one of explicit arguments:

     static void OK_MouseMove(Object self, int x, int y)
     {
         ...
     }

 Not only this requires typing "self.blablabla" all the time (or wrap the
 function into with-block), but you also have to cast self to whatever
 class it actually is...


Apr 02 2002
parent reply "Walter" <walter digitalmars.com> writes:
Hmm. I wonder if the "pointer to function" part is a vtbl[] index or a hard
pointer.

"J. Daniel Smith" <j_daniel_smith HoTMaiL.com> wrote in message
news:a8cr62$29g9$1 digitaldaemon.com...
 In C# (actually, the .NET framework), an object pointer and a pointer to

 of its member functions are wrapped up into a single object called a
 "Delegate", the C# "delegate" keyword makes it easy to create a Delegate
 object.  An Event object is a collection of delegates; the collection

 is a "set" because 1) a calling order is not defined and 2) adding the

 delegate twice does not result in two calls.

    Dan

 "Walter" <walter digitalmars.com> wrote in message
 news:a8corb$28g2$1 digitaldaemon.com...
 So, "event" consists of both an object pointer and a virtual function?


 the event an array of these, called sequentially, or only the "top of

 last entry is called?

 "Pavel Minayev" <evilone omen.ru> wrote in message
 news:a8afmg$sb6$1 digitaldaemon.com...
 "Walter" <walter digitalmars.com> wrote in message
 news:a8ad5n$r5c$1 digitaldaemon.com...

 The problem is I don't understand the problem. I've been buried with


 lately, and haven't given that issue the attention it needs. -Walter

First of all, an example: class Button { event void onMouseMove(int, int); // event (pointer to

         ...
         void mouseMoved(int x, int y)
         {
             // raise event (will first call OK_MouseMove1, then
 OK_MouseMove2)
             onMouseMove(x, y);
         }
     }

     void OK_MouseMove1(int x, int y)    // global event handler
     {
         ...
     }

     class MyForm: Form
     {
         Button OK;

         void OK_MouseMove2(int x, int y)    // local event handler
         {
             ...
         }

         this()
         {
             OK.onMouseMove = OK_MouseMove1;    // set event handler
             OK.onMouseMove ~= OK_MouseMove2;   // add another handler
         }

     }

 Advantage of this approach is that you can make global, static, and
 nonstatic
 member functions event handlers - unlike usual function pointers,



 only allow global and static functions. In most cases, event handler



 actually part of the class, and now, to make it work, it needs to be
 declared static, and to get "this" pointer as one of explicit



     static void OK_MouseMove(Object self, int x, int y)
     {
         ...
     }

 Not only this requires typing "self.blablabla" all the time (or wrap



 function into with-block), but you also have to cast self to whatever
 class it actually is...



Apr 02 2002
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Walter" <walter digitalmars.com> wrote in message
news:a8ct2q$2ain$1 digitaldaemon.com...

 Hmm. I wonder if the "pointer to function" part is a vtbl[] index or a

 pointer.

There's no reason in storing index to vtbl, since you have a pointer to _object_, not _class_ - and object's class (and thus all vtbl entries) is known at run-time. So, when you write &foo, the compiler looks for this function in the vtbl, gets the pointer, and stores it into the delegate struct.
Apr 02 2002
parent reply "Walter" <walter digitalmars.com> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:a8ctft$2ao5$1 digitaldaemon.com...
 "Walter" <walter digitalmars.com> wrote in message
 news:a8ct2q$2ain$1 digitaldaemon.com...
 Hmm. I wonder if the "pointer to function" part is a vtbl[] index or a

 pointer.

_object_, not _class_ - and object's class (and thus all vtbl entries) is known at run-time. So, when you write &foo, the compiler looks for this function in the vtbl, gets the pointer, and stores it into the delegate struct.

Is it expected to work with non-member functions too, with member functions arbitrarilly mixed in?
Apr 02 2002
next sibling parent Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Walter wrote:

 "Pavel Minayev" <evilone omen.ru> wrote in message
 news:a8ctft$2ao5$1 digitaldaemon.com...
 "Walter" <walter digitalmars.com> wrote in message
 news:a8ct2q$2ain$1 digitaldaemon.com...
 Hmm. I wonder if the "pointer to function" part is a vtbl[] index or a

 pointer.

_object_, not _class_ - and object's class (and thus all vtbl entries) is known at run-time. So, when you write &foo, the compiler looks for this function in the vtbl, gets the pointer, and stores it into the delegate struct.

Is it expected to work with non-member functions too, with member functions arbitrarilly mixed in?

It would be nice to have a type that could mix pointer-to-member-function-with-object and pointer-to-global-function, but this might be too much to ask for from the compiler. -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Apr 02 2002
prev sibling parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Walter" <walter digitalmars.com> wrote in message
news:a8d3t1$2em9$1 digitaldaemon.com...

 Is it expected to work with non-member functions too, with member

 arbitrarilly mixed in?

It would be just great (and it is the way C# delegates work). Practically, internals could look like this: // format of delegate pointer struct Delegate { Object obj; void* func; } class Form { void bar(int n); } Form foo; void baz(int n); delegate void ptr(int); // declare delegate pointer ptr = &foo.bar; // store pointer to method bar() of object foo /* Implemented as: ptr.obj = foo; ptr.func = &foo.classinfo.vtbl[bar]; */ ptr(666); // call it /* Implemented as: if (obj != null) // member function (our case) (cast(void (*ptr)(Object, int)) ptr.func)(obj, 666); else // static function (cast(void (*ptr)(int)) ptr.func)(666); */ ptr = &baz; // store pointer to function baz() /* Implemented as: ptr.obj = null; ptr.func = &baz; */ ptr(666); // call it /* Implemented as: if (obj != null) // member function (cast(void (*ptr)(Object, int)) ptr.func)(obj, 666); else // static function (our case) (cast(void (*ptr)(int)) ptr.func)(666); */ As you can see, the check is done at run-time. This makes things a bit slower, but more flexible. For example, you could write: // sorts array of strings, using user-defined comparison function void sort(char[][] s, delegate int cmp(char[], char[])); int my_sort(char[] s1, char[] s2); sort(foo, &my_sort); class Bar { bit case_sensitive; int bar_sort(char[] s1, char[] s2) { if (this.case_sensitive) ... else ... } void baz() { sort(foo, &bar_sort); } }
Apr 02 2002
next sibling parent "J. Daniel Smith" <j_daniel_smith HoTMaiL.com> writes:
I think the C# compiler uses some reflection stuff so that it can do
typechecking at compile time.  With some effort in C++, you can do it all
with templates; but that's not an option in either C# or D.

   Dan

"Pavel Minayev" <evilone omen.ru> wrote in message
news:a8d552$2fc7$1 digitaldaemon.com...
 "Walter" <walter digitalmars.com> wrote in message
 news:a8d3t1$2em9$1 digitaldaemon.com...

 Is it expected to work with non-member functions too, with member

 arbitrarilly mixed in?

It would be just great (and it is the way C# delegates work). Practically, internals could look like this: // format of delegate pointer struct Delegate { Object obj; void* func; } class Form { void bar(int n); } Form foo; void baz(int n); delegate void ptr(int); // declare delegate pointer ptr = &foo.bar; // store pointer to method bar() of object foo /* Implemented as: ptr.obj = foo; ptr.func = &foo.classinfo.vtbl[bar]; */ ptr(666); // call it /* Implemented as: if (obj != null) // member function (our case) (cast(void (*ptr)(Object, int)) ptr.func)(obj, 666); else // static function (cast(void (*ptr)(int)) ptr.func)(666); */ ptr = &baz; // store pointer to function baz() /* Implemented as: ptr.obj = null; ptr.func = &baz; */ ptr(666); // call it /* Implemented as: if (obj != null) // member function (cast(void (*ptr)(Object, int)) ptr.func)(obj, 666); else // static function (our case) (cast(void (*ptr)(int)) ptr.func)(666); */ As you can see, the check is done at run-time. This makes things a bit slower, but more flexible. For example, you could write: // sorts array of strings, using user-defined comparison function void sort(char[][] s, delegate int cmp(char[], char[])); int my_sort(char[] s1, char[] s2); sort(foo, &my_sort); class Bar { bit case_sensitive; int bar_sort(char[] s1, char[] s2) { if (this.case_sensitive) ... else ... } void baz() { sort(foo, &bar_sort); } }

Apr 02 2002
prev sibling parent reply "Walter" <walter digitalmars.com> writes:
The C# syntax I find very confusing. The delegate declaration looks like a
storage class, but it isn't, it's a type component. It doesn't seem possible
in C#, because of the way declarations work, to create an array of delegates
or a pointer to a delegate or a function returning a delegate.

The static/virtual delegate call shouldn't cause a slowdown in D, for the
happy coincidence that the 'this' pointer is passed in EAX. Hence, just
stuff the object reference in EAX after pushing the parameters. If the
function doesn't take a this pointer, it ignores EAX with no adverse
consequences.

"Pavel Minayev" <evilone omen.ru> wrote in message
news:a8d552$2fc7$1 digitaldaemon.com...
 "Walter" <walter digitalmars.com> wrote in message
 news:a8d3t1$2em9$1 digitaldaemon.com...

 Is it expected to work with non-member functions too, with member

 arbitrarilly mixed in?

It would be just great (and it is the way C# delegates work). Practically, internals could look like this: // format of delegate pointer struct Delegate { Object obj; void* func; } class Form { void bar(int n); } Form foo; void baz(int n); delegate void ptr(int); // declare delegate pointer ptr = &foo.bar; // store pointer to method bar() of object foo /* Implemented as: ptr.obj = foo; ptr.func = &foo.classinfo.vtbl[bar]; */ ptr(666); // call it /* Implemented as: if (obj != null) // member function (our case) (cast(void (*ptr)(Object, int)) ptr.func)(obj, 666); else // static function (cast(void (*ptr)(int)) ptr.func)(666); */ ptr = &baz; // store pointer to function baz() /* Implemented as: ptr.obj = null; ptr.func = &baz; */ ptr(666); // call it /* Implemented as: if (obj != null) // member function (cast(void (*ptr)(Object, int)) ptr.func)(obj, 666); else // static function (our case) (cast(void (*ptr)(int)) ptr.func)(666); */ As you can see, the check is done at run-time. This makes things a bit slower, but more flexible. For example, you could write: // sorts array of strings, using user-defined comparison function void sort(char[][] s, delegate int cmp(char[], char[])); int my_sort(char[] s1, char[] s2); sort(foo, &my_sort); class Bar { bit case_sensitive; int bar_sort(char[] s1, char[] s2) { if (this.case_sensitive) ... else ... } void baz() { sort(foo, &bar_sort); } }

Apr 03 2002
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Walter" <walter digitalmars.com> wrote in message
news:a8eie6$40d$1 digitaldaemon.com...

 The C# syntax I find very confusing. The delegate declaration looks like a
 storage class, but it isn't, it's a type component. It doesn't seem

 in C#, because of the way declarations work, to create an array of

 or a pointer to a delegate or a function returning a delegate.

It wasn't actually C# syntax. In C#, "delegate" is actually a keyword which declares type, and not variable: delegate void Foo(int); // Foo is a new type Foo ptr; // declare a pointer of that type So, you can actually have arrays: Foo[] ptr; Still, I like your syntax more. It is more distinct from normal function declaration.
 The static/virtual delegate call shouldn't cause a slowdown in D, for the
 happy coincidence that the 'this' pointer is passed in EAX. Hence, just
 stuff the object reference in EAX after pushing the parameters. If the
 function doesn't take a this pointer, it ignores EAX with no adverse
 consequences.

It's implementation detail, I guess. As long as it works, great, and no matter how it is done. I wouldn't mind if it were slower than normal ptr call, but if you can make it the same, well, it's great! By the way, I guess functions with non-D calling conventions cannot be delegated?
Apr 03 2002
parent "Walter" <walter digitalmars.com> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:a8evkh$5tf$1 digitaldaemon.com...
 "Walter" <walter digitalmars.com> wrote in message
 news:a8eie6$40d$1 digitaldaemon.com...
 The C# syntax I find very confusing. The delegate declaration looks like


 storage class, but it isn't, it's a type component. It doesn't seem

 in C#, because of the way declarations work, to create an array of

 or a pointer to a delegate or a function returning a delegate.

which declares type, and not variable: delegate void Foo(int); // Foo is a new type Foo ptr; // declare a pointer of that type So, you can actually have arrays: Foo[] ptr;

That completely threw me. If the descriptions would just *say* that it was a wierd form of typedef, it would have made a lot more sense to me. I couldn't figure out if it was declaring a delegate type, a variable of type delegate, or a function to be delegated, hence I couldn't figure out what a delegate was. I looked at several descriptions of it via Google, and they were all a mess. Needless to say, I am not going to do it that way in D!
 Still, I like your syntax more. It is more distinct from normal
 function declaration.

Thanks for pointing out the conceptual simplicity of it just being a function pointer bundled with an object reference. I guess I tend to think about programming concepts differently than others, I see complexity where they see simplicity and vice versa <g>. It really is just an enhanced "pointer to function", so it should declare in a manner similar to pointer to function. I thought of using another special character to replace the * in pointer to function, but that got too wierd looking <g>. I considered *., but that looked too confusing with C++ pointers to members.
 By the way, I guess functions with non-D calling conventions cannot
 be delegated?

Sure they can be, they just can't be mixed into one delegate type. This works analogously to the type checking on function pointers.
Apr 03 2002
prev sibling parent reply Patrick Down <pat codemoon.com> writes:
I't a really nice site Pavel.  I do have
one question about your WinD example.  You
have:
        
        static void OK_Click(Object me, Event e)
        {
            me.close();
        }

Shouldn't me be cast to Frame or something?
Mar 31 2002
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Patrick Down" <pat codemoon.com> wrote in message
news:Xns91E2EF11F18F2patcodemooncom 63.105.9.61...

 I't a really nice site Pavel.  I do have
 one question about your WinD example.  You
 have:

         static void OK_Click(Object me, Event e)
         {
             me.close();
         }

 Shouldn't me be cast to Frame or something?

Oh yes, you've caught me! I've just done the change to the event system, and corrected the sample properly, but didn't test it =) Now, I prefer to write it this way: static void OK_Click(Object me, Event e) { with (cast(Frame) me) { close(); }}
Mar 31 2002
parent reply "Sean L. Palmer" <spalmer iname.com> writes:
Oh, God, Walter, it's too bad you can't make the D language specification
require reasonable indentation!   ;)

Sean


"Pavel Minayev" <evilone omen.ru> wrote in message
news:a88v29$2q3b$1 digitaldaemon.com...

 Oh yes, you've caught me! I've just done the change to the event system,
 and corrected the sample properly, but didn't test it =)

 Now, I prefer to write it this way:

     static void OK_Click(Object me, Event e) { with (cast(Frame) me)
     {
         close();
     }}

Mar 31 2002
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Sean L. Palmer" <spalmer iname.com> wrote in message
news:a88val$2q6s$1 digitaldaemon.com...

 Oh, God, Walter, it's too bad you can't make the D language specification
 require reasonable indentation!   ;)

Well, he could just make pointers to methods... =)
Apr 01 2002
parent reply Svyatoslav Bezgin <Kirdyk dcd.tstu.ru> writes:
 Oh, God, Walter, it's too bad you can't make the D language specification
 require reasonable indentation!   ;)


I think it'll be more convinient to develop software using it.... I ask You about it. Not only for me, but for whole Dcommunity....
Apr 01 2002
parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Svyatoslav Bezgin wrote:

 I ask You about it. Not only for me, but for whole Dcommunity....

Maybe, since we're moving from C to D, we should be known as a dommunity... :) -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Apr 01 2002
parent reply "OddesE" <OddesE_XYZ hotmail.com> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3CA8C79E.703CAD34 deming-os.org...
 Svyatoslav Bezgin wrote:

 I ask You about it. Not only for me, but for whole Dcommunity....

Maybe, since we're moving from C to D, we should be known as a

 --
 The Villagers are Online! villagersonline.com

 .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
 .[ (a version.of(English).(precise.more)) is(possible) ]
 ?[ you want.to(help(develop(it))) ]

But in Dutch 'dom' means stupid... :( -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net _________________________________________________ Remove _XYZ from my address when replying by mail
Apr 02 2002
parent reply "Robert W. Cunningham" <rwc_2001 yahoo.com> writes:
OddesE wrote:

 "Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
 news:3CA8C79E.703CAD34 deming-os.org...
 Svyatoslav Bezgin wrote:

 I ask You about it. Not only for me, but for whole Dcommunity....

Maybe, since we're moving from C to D, we should be known as a

 --
 The Villagers are Online! villagersonline.com

 .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
 .[ (a version.of(English).(precise.more)) is(possible) ]
 ?[ you want.to(help(develop(it))) ]

But in Dutch 'dom' means stupid... :(

Yeah, but it's not like we want to be called the "Kaas Kopmunity"... -BobC
Apr 02 2002
parent "OddesE" <OddesE_XYZ hotmail.com> writes:
"Robert W. Cunningham" <rwc_2001 yahoo.com> wrote in message
news:3CAA7EAF.A410548E yahoo.com...
 OddesE wrote:

 "Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
 news:3CA8C79E.703CAD34 deming-os.org...
 Svyatoslav Bezgin wrote:

 I ask You about it. Not only for me, but for whole Dcommunity....

Maybe, since we're moving from C to D, we should be known as a

 --
 The Villagers are Online! villagersonline.com

 .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
 .[ (a version.of(English).(precise.more)) is(possible) ]
 ?[ you want.to(help(develop(it))) ]

But in Dutch 'dom' means stupid... :(

Yeah, but it's not like we want to be called the "Kaas Kopmunity"... -BobC

LOL! How did you know? Do you have friends in Holland? :) -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net _________________________________________________ Remove _XYZ from my address when replying by mail
Apr 03 2002