Assigning a member function to signal callback function pointer

Discussion in 'C++' started by Ramesh, Dec 25, 2008.

  1. Ramesh

    Ramesh Guest

    Hello,

    I am writing an application in linux using timer_create API to create
    timers in my application, I have registered a call back routine which
    would be called when the timer timesout. I get the following error:

    -------

    test.cpp: In member function 'unsigned long
    testMgr::addConfigChangeTimer(unsigned long)':
    test.cpp:125: error: argument of type 'void (testMgr::)(sigval_t)'
    does not match 'void (*)(sigval_t)'

    ------

    The compiler expects a function returning void and taking a sigval_t
    as argument, in my case the only difference is that the linkage is C++
    style and its a member function.

    Is there a way I can assign a member function to the notify_function
    pointer?

    Thanks
    /R



    Here is the code snippet:

    ---

    // Actual point of assignment of the callback function to the signal
    handler

    unsigned long testMgr::addConfigChangeTimer(unsigned long interval) {

    timer_t id = 0;
    int count = 0;
    struct sigevent sig;
    struct itimerspec timerspec;

    memset(&timerspec, 0, sizeof(struct itimerspec));
    memset(&sig, 0, sizeof(struct sigevent));

    sig.sigev_notify = SIGEV_THREAD;
    sig.sigev_notify_function = ConfigChangeHandler;

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    sig.sigev_value.sival_ptr = (void*)&count

    -------

    // Actual function


    void testMgr::ConfigChangeHandler(sigval_t value) {

    ACE_Guard<ACE_Thread_Mutex> guard(tMutex);

    if (ConfigChange == TRUE) {
    Notifythreads();
    ConfigChange = FALSE;
    }
    trace("Config change timeout process completed");
    }

    ----

    // Class definition

    class testMgr {

    private:

    timestamp ChangeTime;
    BOOL ConfigChange;
    ACE_Thread_Mutex tMutex;

    public:

    testMgr();
    ~testMgr();
    UINT32 addConfigChangeTimer(UINT32);
    void entConfigChangeHandler(sigval_t );
    };
     
    Ramesh, Dec 25, 2008
    #1
    1. Advertising

  2. Ramesh

    Guest

    On Dec 24, 7:04 pm, Ramesh <> wrote:
    > Hello,
    >
    > I am writing an application in linux using timer_create API to create
    > timers in my application, I have registered a call back routine which
    > would be called when the timer timesout. I get the following error:
    >
    > -------
    >
    > test.cpp: In member function 'unsigned long
    > testMgr::addConfigChangeTimer(unsigned long)':
    > test.cpp:125: error: argument of type 'void (testMgr::)(sigval_t)'
    > does not match 'void (*)(sigval_t)'
    >
    > ------
    >
    > The compiler expects a function returning void and taking a sigval_t
    > as argument, in my case the only difference is that the linkage is C++
    > style and its a member function.
    >
    > Is there a way I can assign a member function to the notify_function
    > pointer?
    >
    > Thanks
    > /R
    >
    > Here is the code snippet:
    >
    > ---
    >
    > // Actual point of assignment of the callback function to the signal
    > handler
    >
    > unsigned long testMgr::addConfigChangeTimer(unsigned long interval) {
    >
    >     timer_t id                  = 0;
    >     int count                   = 0;
    >     struct sigevent sig;
    >     struct itimerspec timerspec;
    >
    >     memset(&timerspec, 0, sizeof(struct itimerspec));
    >     memset(&sig, 0, sizeof(struct sigevent));
    >
    >     sig.sigev_notify            = SIGEV_THREAD;
    >     sig.sigev_notify_function   = ConfigChangeHandler;
    >
    > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    >     sig.sigev_value.sival_ptr   = (void*)&count


    Do you actually mean to pass the address of the local variable count
    to an asynchronous callback function here?

    Anyways, like Sam said you can't pass a pointer to a member function
    as a callback and expect it to be called on the appropriate instance
    of the object. Pointer-to-members do exist, and you can use them but
    only if you also supply an instance of a class. The compiler error you
    received is because you attempted to pass a pointer to a non-static
    member function but it was expecting a pointer to a static/non-member
    function (the two have different types).

    Instead, pass your 'this' pointer through sig.sigev_value.sival_ptr,
    and make your callback a static function. Then your callback can
    either do what it needs to do or pass control off to a non-static
    member function appropriately, e.g.:


    class testMgr {
    public:
    unsigned long addConfigChangeTimer (unsigned long);
    private:
    void ConfigChangeHandler ();
    static void StaticConfigChangeHandler (sigval_t value);
    };


    unsigned long testMgr::addConfigChangeTimer (unsigned long) {
    ...
    sig.sigev_notify_function = StaticConfigChangeHandler;
    sig.sigev_value.sival_ptr = (void *)this;
    ...
    }


    void testMgr::StaticConfigChangeHandler (sigval_t value) {
    // pass control to member function.
    assert(value.sival_ptr);
    ((testMgr *)value.sival_ptr)->ConfigChangeHandler();
    }


    void testMgr::ConfigChangeHandler () {
    // do stuff.
    ...
    }


    If you want to pass additional context data to ConfigChangeHandler
    then you'll have to pack stuff in to some kind of structure, e.g.:

    struct ConfigChangeHandlerParams {
    ConfigChangeHandler *inst;
    int *pcount;
    };


    void testMgr::StaticConfigChangeHandler (sigval_t value) {
    // for example, passing pcount:
    assert(value.sival_ptr);
    ConfigChangeHandlerParams *p = (ConfigChangeHandlerParams *)
    value.sival_ptr;
    p->inst->ConfigChangeHandler(p->pcount);
    }


    Managing ConfigChangeHandlerParams structs in an exception-safe way is
    left as an exercise.

    HTH,
    Jason


    >
    > -------
    >
    > // Actual function
    >
    > void testMgr::ConfigChangeHandler(sigval_t value) {
    >
    >     ACE_Guard<ACE_Thread_Mutex> guard(tMutex);
    >
    >     if (ConfigChange == TRUE) {
    >         Notifythreads();
    >         ConfigChange = FALSE;
    >     }
    >     trace("Config change timeout process completed");
    >
    > }
    >
    > ----
    >
    > // Class definition
    >
    > class testMgr {
    >
    >         private:
    >
    >                 timestamp           ChangeTime;
    >                 BOOL                ConfigChange;
    >                 ACE_Thread_Mutex    tMutex;
    >
    >         public:
    >
    >                 testMgr();
    >                 ~testMgr();
    >                 UINT32          addConfigChangeTimer(UINT32);
    >                 void            entConfigChangeHandler(sigval_t );
    >
    > };
    >
    >
     
    , Dec 25, 2008
    #2
    1. Advertising

  3. Ramesh

    red floyd Guest

    Ramesh wrote:
    > Hello,
    >
    > I am writing an application in linux using timer_create API to create
    > timers in my application, I have registered a call back routine which
    > would be called when the timer timesout. I get the following error:
    >
    > -------
    >
    > test.cpp: In member function 'unsigned long
    > testMgr::addConfigChangeTimer(unsigned long)':
    > test.cpp:125: error: argument of type 'void (testMgr::)(sigval_t)'
    > does not match 'void (*)(sigval_t)'
    >
    > ------
    >
    > The compiler expects a function returning void and taking a sigval_t
    > as argument, in my case the only difference is that the linkage is C++
    > style and its a member function.
    >
    > Is there a way I can assign a member function to the notify_function
    > pointer?
    >


    This is a FAQ. FAQ 33.2 to be precise.

    http://www.parashift.com/c -faq-lite/pointers-to-members.html#faq-33.2
     
    red floyd, Dec 25, 2008
    #3
  4. Ramesh

    Ian Collins Guest

    Sam wrote:
    >
    > Recall that an ordinary class member function has access to member
    > variables of an individual class instance. You may think that by passing
    > a pointer to a member function from another member function, as a
    > callback function, when the callback function gets invoked it will be
    > invoked for the same class instance, but this is not the case. The
    > timer_create API doesn't know about any objects, it only takes an
    > ordinary function pointer. With C++, a function pointer is not enough,
    > you need a class instance to go with it.
    >
    > Unless, of course, it's a static class member function that's not
    > associated with any class instance.
    >

    Which still isn't a valid function to pass to a C interface, the linkage
    is wrong.

    --
    Ian Collins
     
    Ian Collins, Dec 25, 2008
    #4
  5. Ramesh

    Guest

    On Dec 24, 11:24 pm, Ian Collins <> wrote:
    > Sam wrote:
    >
    > > Recall that an ordinary class member function has access to member
    > > variables of an individual class instance. You may think that by passing
    > > a pointer to a member function from another member function, as a
    > > callback function, when the callback function gets invoked it will be
    > > invoked for the same class instance, but this is not the case. The
    > > timer_create API doesn't know about any objects, it only takes an
    > > ordinary function pointer. With C++, a function pointer is not enough,
    > > you need a class instance to go with it.

    >
    > > Unless, of course, it's a static class member function that's not
    > > associated with any class instance.

    >
    > Which still isn't a valid function to pass to a C interface, the linkage
    > is wrong.


    You may mean "calling convention", not "linkage", although in all
    compilers that I know of that let you specify the calling convention,
    it's part of the type (e.g. __stdcall vs. __cdecl with MSVC).

    Passing C++ function pointers to functions with C linkage is not an
    issue, the linkage is used by the linker, but passing function
    pointers around is not the same as linking object files together.
    Linkage doesn't come into play there.

    JC
     
    , Dec 25, 2008
    #5
  6. Ramesh

    Ian Collins Guest

    wrote:
    > On Dec 24, 11:24 pm, Ian Collins <> wrote:
    >> Sam wrote:
    >>
    >>> Recall that an ordinary class member function has access to member
    >>> variables of an individual class instance. You may think that by passing
    >>> a pointer to a member function from another member function, as a
    >>> callback function, when the callback function gets invoked it will be
    >>> invoked for the same class instance, but this is not the case. The
    >>> timer_create API doesn't know about any objects, it only takes an
    >>> ordinary function pointer. With C++, a function pointer is not enough,
    >>> you need a class instance to go with it.
    >>> Unless, of course, it's a static class member function that's not
    >>> associated with any class instance.

    >> Which still isn't a valid function to pass to a C interface, the linkage
    >> is wrong.

    >
    > You may mean "calling convention", not "linkage", although in all
    > compilers that I know of that let you specify the calling convention,
    > it's part of the type (e.g. __stdcall vs. __cdecl with MSVC).
    >

    No, I should have said "Linkage specification". Nothing to do with
    calling conventions. A static member function does not have extern "C"
    linkage.

    > Passing C++ function pointers to functions with C linkage is not an
    > issue, the linkage is used by the linker, but passing function
    > pointers around is not the same as linking object files together.
    > Linkage doesn't come into play there.
    >

    Passing a pointer to a C++ function to a function expecting a pointer to
    a C function is an issue, although many compilers will ignore the
    difference. Others aren't so lax.

    --
    Ian Collins
     
    Ian Collins, Dec 25, 2008
    #6
  7. Ramesh

    James Kanze Guest

    On Dec 25, 9:11 am, Ian Collins <> wrote:
    > wrote:
    > > On Dec 24, 11:24 pm, Ian Collins <> wrote:
    > >> Sam wrote:


    > >>> Recall that an ordinary class member function has access
    > >>> to member variables of an individual class instance. You
    > >>> may think that by passing a pointer to a member function
    > >>> from another member function, as a callback function, when
    > >>> the callback function gets invoked it will be invoked for
    > >>> the same class instance, but this is not the case. The
    > >>> timer_create API doesn't know about any objects, it only
    > >>> takes an ordinary function pointer. With C++, a function
    > >>> pointer is not enough, you need a class instance to go
    > >>> with it. Unless, of course, it's a static class member
    > >>> function that's not associated with any class instance.


    > >> Which still isn't a valid function to pass to a C
    > >> interface, the linkage is wrong.


    > > You may mean "calling convention", not "linkage", although
    > > in all compilers that I know of that let you specify the
    > > calling convention, it's part of the type (e.g. __stdcall
    > > vs. __cdecl with MSVC).


    The standard specifies a means of specifying the calling
    convention; it's called a linkage specification.

    > No, I should have said "Linkage specification". Nothing to do
    > with calling conventions.


    Linkage specification is the C++ syntax for specifying the
    calling conventions: "C++", "C", "Fortran", etc. ("C++" and "C"
    are required; any others are implementation defined.)

    > A static member function does not have extern "C" linkage.


    More precisely, "A C language linkage is ignored for the names
    of class members and the member function type of class member
    functions."

    > > Passing C++ function pointers to functions with C linkage is
    > > not an issue, the linkage is used by the linker, but passing
    > > function pointers around is not the same as linking object
    > > files together. Linkage doesn't come into play there.


    > Passing a pointer to a C++ function to a function expecting a
    > pointer to a C function is an issue, although many compilers
    > will ignore the difference. Others aren't so lax.


    The linkage is part of the type. Using the address of a
    function with C++ linkage to initialize a pointer to a function
    with C linkage is a diagnosable error; a C++ compiler is
    required to emit a diagnostic. Some compilers have bugs,
    however, and don't. (And why Microsoft decided to invent a
    completely different mechanism, when the standard already
    defined one, I don't know. Logically, instead of new keywords,
    I would have expected ``extern "stdcall"'', etc. Not that it
    makes much difference in practice.)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Dec 25, 2008
    #7
  8. Ramesh

    Ramesh Guest

    On Dec 25, 5:27 am, James Kanze <> wrote:
    > On Dec 25, 9:11 am, Ian Collins <> wrote:
    >
    >
    >
    > > wrote:
    > > > On Dec 24, 11:24 pm, Ian Collins <> wrote:
    > > >> Sam wrote:
    > > >>> Recall that an ordinary class member function has access
    > > >>> to member variables of an individual class instance. You
    > > >>> may think that by passing a pointer to a member function
    > > >>> from another member function, as a callback function, when
    > > >>> the callback function gets invoked it will be invoked for
    > > >>> the same class instance, but this is not the case. The
    > > >>> timer_create API doesn't know about any objects, it only
    > > >>> takes an ordinary function pointer. With C++, a function
    > > >>> pointer is not enough, you need a class instance to go
    > > >>> with it.  Unless, of course, it's a static class member
    > > >>> function that's not associated with any class instance.
    > > >> Which still isn't a valid function to pass to a C
    > > >> interface, the linkage is wrong.
    > > > You may mean "calling convention", not "linkage", although
    > > > in all compilers that I know of that let you specify the
    > > > calling convention, it's part of the type (e.g. __stdcall
    > > > vs. __cdecl with MSVC).

    >
    > The standard specifies a means of specifying the calling
    > convention; it's called a linkage specification.
    >
    > > No, I should have said "Linkage specification".  Nothing to do
    > > with calling conventions.

    >
    > Linkage specification is the C++ syntax for specifying the
    > calling conventions: "C++", "C", "Fortran", etc.  ("C++" and "C"
    > are required; any others are implementation defined.)
    >
    > > A static member function does not have extern "C" linkage.

    >
    > More precisely, "A C language linkage is ignored for the names
    > of class members and the member function type of class member
    > functions."
    >
    > > > Passing C++ function pointers to functions with C linkage is
    > > > not an issue, the linkage is used by the linker, but passing
    > > > function pointers around is not the same as linking object
    > > > files together.  Linkage doesn't come into play there.

    > > Passing a pointer to a C++ function to a function expecting a
    > > pointer to a C function is an issue, although many compilers
    > > will ignore the difference.  Others aren't so lax.

    >
    > The linkage is part of the type.  Using the address of a
    > function with C++ linkage to initialize a pointer to a function
    > with C linkage is a diagnosable error; a C++ compiler is
    > required to emit a diagnostic.  Some compilers have bugs,
    > however, and don't.  (And why Microsoft decided to invent a
    > completely different mechanism, when the standard already
    > defined one, I don't know.  Logically, instead of new keywords,
    > I would have expected ``extern "stdcall"'', etc.  Not that it
    > makes much difference in practice.)
    >
    > --
    > James Kanze (GABI Software)             email:
    > Conseils en informatique orientée objet/
    >                    Beratung in objektorientierter Datenverarbeitung
    > 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


    Thanks a bunch.

    Cheers
    /R
     
    Ramesh, Dec 25, 2008
    #8
  9. Ramesh

    Rolf Magnus Guest

    James Kanze wrote:

    >> >> Which still isn't a valid function to pass to a C
    >> >> interface, the linkage is wrong.

    >
    >> > You may mean "calling convention", not "linkage", although
    >> > in all compilers that I know of that let you specify the
    >> > calling convention, it's part of the type (e.g. __stdcall
    >> > vs. __cdecl with MSVC).

    >
    > The standard specifies a means of specifying the calling
    > convention; it's called a linkage specification.
    >
    >> No, I should have said "Linkage specification". Nothing to do
    >> with calling conventions.

    >
    > Linkage specification is the C++ syntax for specifying the
    > calling conventions: "C++", "C", "Fortran", etc. ("C++" and "C"
    > are required; any others are implementation defined.)


    Well, "linkage" contains everything that is involved in being able to call
    functions defined in the other language. That includes calling conventions as
    well as name mangling.

    >> Passing a pointer to a C++ function to a function expecting a
    >> pointer to a C function is an issue, although many compilers
    >> will ignore the difference. Others aren't so lax.

    >
    > The linkage is part of the type. Using the address of a
    > function with C++ linkage to initialize a pointer to a function
    > with C linkage is a diagnosable error; a C++ compiler is
    > required to emit a diagnostic. Some compilers have bugs,
    > however, and don't. (And why Microsoft decided to invent a
    > completely different mechanism, when the standard already
    > defined one, I don't know. Logically, instead of new keywords,
    > I would have expected ``extern "stdcall"'', etc. Not that it
    > makes much difference in practice.)


    My guess is that this is simply because that C++ feature doesn't exist in C
    and because the Microsoft variant is older than the C++ mechanism.
     
    Rolf Magnus, Dec 25, 2008
    #9
  10. Ramesh

    Guest

    On Dec 25, 8:27 am, James Kanze <> wrote:
    > (And why Microsoft decided to invent a
    > completely different mechanism, when the standard already
    > defined one, I don't know.  Logically, instead of new keywords,
    > I would have expected ``extern "stdcall"'', etc.  Not that it
    > makes much difference in practice.)


    This is because it was actually a Microsoft extension to C that made
    it into C++ for easier compatibility with the Windows API, which is
    all C. Same deal with their SEH stuff (__try, __except, __finally,
    etc., which can actually catch hardware exceptions like access
    violations as well) -- those are available in MS C++ even though C++
    defines an exception handling mechanism, but they were originally
    extensions to C.

    By the way, just a little bit of trivia, Borland made it even more
    annoying by having their __fastcall use different semantics than
    Microsoft's __fastcall, and then later introducing __msfastcall (which
    means the same thing as __fastcall on MS compilers). That's a pretty
    subtle one that can bite you if you're moving between MS and Borland
    compilers, which are otherwise extremely similar -- that is, if you're
    using __fastcall in the first place.

    Jason
     
    , Dec 27, 2008
    #10
  11. Ramesh

    James Kanze Guest

    On Dec 25, 9:21 pm, Rolf Magnus <> wrote:
    > James Kanze wrote:
    > >> >> Which still isn't a valid function to pass to a C
    > >> >> interface, the linkage is wrong.


    > >> > You may mean "calling convention", not "linkage", although
    > >> > in all compilers that I know of that let you specify the
    > >> > calling convention, it's part of the type (e.g. __stdcall
    > >> > vs. __cdecl with MSVC).


    > > The standard specifies a means of specifying the calling
    > > convention; it's called a linkage specification.


    > >> No, I should have said "Linkage specification". Nothing to do
    > >> with calling conventions.


    > > Linkage specification is the C++ syntax for specifying the
    > > calling conventions: "C++", "C", "Fortran", etc. ("C++" and
    > > "C" are required; any others are implementation defined.)


    > Well, "linkage" contains everything that is involved in being
    > able to call functions defined in the other language. That
    > includes calling conventions as well as name mangling.


    And anything else that might be needed. I've usually heard
    "calling conventions" used for all of it. But of course, that
    was before type safe name mangling was used: the "calling
    convention" was typically something along the lines of
    prefixing a '_' to the name.

    > >> Passing a pointer to a C++ function to a function expecting
    > >> a pointer to a C function is an issue, although many
    > >> compilers will ignore the difference. Others aren't so
    > >> lax.


    > > The linkage is part of the type. Using the address of a
    > > function with C++ linkage to initialize a pointer to a
    > > function with C linkage is a diagnosable error; a C++
    > > compiler is required to emit a diagnostic. Some compilers
    > > have bugs, however, and don't. (And why Microsoft decided
    > > to invent a completely different mechanism, when the
    > > standard already defined one, I don't know. Logically,
    > > instead of new keywords, I would have expected ``extern
    > > "stdcall"'', etc. Not that it makes much difference in
    > > practice.)


    > My guess is that this is simply because that C++ feature
    > doesn't exist in C and because the Microsoft variant is older
    > than the C++ mechanism.


    The C++ mechanism dates to well before Microsoft had a C++
    compiler, or were even developing one.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Dec 27, 2008
    #11
  12. Ramesh

    James Kanze Guest

    On Dec 27, 6:01 am, ""
    <> wrote:
    > On Dec 25, 8:27 am, James Kanze <> wrote:


    > > (And why Microsoft decided to invent a completely different
    > > mechanism, when the standard already defined one, I don't
    > > know. Logically, instead of new keywords, I would have
    > > expected ``extern "stdcall"'', etc. Not that it makes much
    > > difference in practice.)


    > This is because it was actually a Microsoft extension to C
    > that made it into C++ for easier compatibility with the
    > Windows API, which is all C.


    OK. If it's from C, it's understandable; C doesn't provide a
    standard syntax for this. Still, in their place, I'd have
    specified the standard syntax to handle it, and just kept the
    other for reasons of backward (or C) compatibility.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Dec 27, 2008
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Newsgroup - Ann
    Replies:
    5
    Views:
    667
    John Carson
    Jul 30, 2003
  2. Fraser Ross
    Replies:
    4
    Views:
    1,098
    Fraser Ross
    Aug 14, 2004
  3. Stephen Howe
    Replies:
    2
    Views:
    309
    Stephen Howe
    Nov 6, 2012
  4. somenath
    Replies:
    10
    Views:
    314
    James Kanze
    Jul 2, 2013
  5. somenath
    Replies:
    2
    Views:
    179
    somenath
    Aug 29, 2013
Loading...

Share This Page