www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to use a member function (delegate) as a function pointer

reply Peter Federighi <pfederighi yahoo.com> writes:
Hello.  I'm new to D. It's been a long time since I've coded anything with
classes.  Please excuse my ignorance.

Here's a very simplified version of what I'm trying to do:

import std.c.linux.linux;
import std.stdio;
class FOO
    {
    this()
        {
        sa.sa_handler = &handler;
        sigemptyset(&sa.sa_mask);
        sa.sa_flags = SA_RESTART;
        sigaction(SIGALRM, &sa, null);
        }

    ~this()
        {
        sa.sa_handler = SIG_DFL;
        sigemptyset(&sa.sa_mask);
        sa.sa_flags = SA_RESTART;
        sigaction(SIGALRM, &sa, null);
        }

    private:
    sigaction_t sa;

    void handler(int signal)
        {
        writeln("Got an alarm signal.");
        }
    }


Is there a way to do it without removing handler() from the class?  When I try
compiling, I get: Error: cannot implicitly convert expression (&this.handler)
of type void delegate(int signal) to void C function(int).

Thank you,
- Peter
Oct 31 2010
next sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Mon, 01 Nov 2010 05:27:06 +0300, Peter Federighi <pfederighi yahoo.com>  
wrote:

 Hello.  I'm new to D. It's been a long time since I've coded anything  
 with
 classes.  Please excuse my ignorance.

 Here's a very simplified version of what I'm trying to do:

 import std.c.linux.linux;
 import std.stdio;
 class FOO
     {
     this()
         {
         sa.sa_handler = &handler;
         sigemptyset(&sa.sa_mask);
         sa.sa_flags = SA_RESTART;
         sigaction(SIGALRM, &sa, null);
         }

     ~this()
         {
         sa.sa_handler = SIG_DFL;
         sigemptyset(&sa.sa_mask);
         sa.sa_flags = SA_RESTART;
         sigaction(SIGALRM, &sa, null);
         }

     private:
     sigaction_t sa;

     void handler(int signal)
         {
         writeln("Got an alarm signal.");
         }
     }


 Is there a way to do it without removing handler() from the class?  When  
 I try
 compiling, I get: Error: cannot implicitly convert expression  
 (&this.handler)
 of type void delegate(int signal) to void C function(int).

 Thank you,
 - Peter

No, unfortunately not. A delegate is a function pointer PLUS 'this'. The C API you are using allows providing function only, without a context. As such, you need to store 'this' pointer somewhere else. It is usually done by means of of a special userData variable which is additionally passed to the callback (looks like we are out of luck this time), or storing it in a global variable: Foo foo; void externalHandler(int signal) { assert(foo !is null); foo.handler(signal); } class Foo { this() { assert(foo is null); foo = this; sa.sa_handler = &externalHandler; // ... } ~this() { assert(foo is this); foo = null; // ... } // ... }
Oct 31 2010
prev sibling parent "Daniel Murphy" <yebblies nospamgmail.com> writes:
"Peter Federighi" <pfederighi yahoo.com> wrote in message 
news:ial8hq$2137$1 digitalmars.com...
 Is there a way to do it without removing handler() from the class?  When I 
 try
 compiling, I get: Error: cannot implicitly convert expression 
 (&this.handler)
 of type void delegate(int signal) to void C function(int).

Yes, but it requires some nasty code. (Not tested on anything except windows) http://yebblies.com/thunk.d (Also not tested) import yebblies.thunk.d; import std.c.linux.linux; import std.stdio; class FOO { this() { th = thunk!"C"(&handler); sa.sa_handler = th.ptr; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; sigaction(SIGALRM, &sa, null); } ~this() { sa.sa_handler = SIG_DFL; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; sigaction(SIGALRM, &sa, null); } private: sigaction_t sa; typeof(thunk!"C"(&handler)) th; void handler(int signal) { writeln("Got an alarm signal."); } } It basically gets around the restriction by writing some code into memory that passes the delegate params in unused registers. I don't even know if the page allocation code works on anything except windows. Daniel
Oct 31 2010