Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Assigning a member function to signal callback function pointer

Reply
Thread Tools

Assigning a member function to signal callback function pointer

 
 
Ramesh
Guest
Posts: n/a
 
      12-25-2008
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 );
};
 
Reply With Quote
 
 
 
 
jason.cipriani@gmail.com
Guest
Posts: n/a
 
      12-25-2008
On Dec 24, 7:04*pm, Ramesh <(E-Mail Removed)> 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 );
>
> };
>
>


 
Reply With Quote
 
 
 
 
red floyd
Guest
Posts: n/a
 
      12-25-2008
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-lit....html#faq-33.2
 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      12-25-2008
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
 
Reply With Quote
 
jason.cipriani@gmail.com
Guest
Posts: n/a
 
      12-25-2008
On Dec 24, 11:24*pm, Ian Collins <(E-Mail Removed)> 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
 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      12-25-2008
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> On Dec 24, 11:24 pm, Ian Collins <(E-Mail Removed)> 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
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      12-25-2008
On Dec 25, 9:11 am, Ian Collins <(E-Mail Removed)> wrote:
> (E-Mail Removed) wrote:
> > On Dec 24, 11:24 pm, Ian Collins <(E-Mail Removed)> 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:(E-Mail Removed)
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
 
Reply With Quote
 
Ramesh
Guest
Posts: n/a
 
      12-25-2008
On Dec 25, 5:27*am, James Kanze <(E-Mail Removed)> wrote:
> On Dec 25, 9:11 am, Ian Collins <(E-Mail Removed)> wrote:
>
>
>
> > (E-Mail Removed) wrote:
> > > On Dec 24, 11:24 pm, Ian Collins <(E-Mail Removed)> 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:(E-Mail Removed)
> 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
 
Reply With Quote
 
Rolf Magnus
Guest
Posts: n/a
 
      12-25-2008
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.

 
Reply With Quote
 
jason.cipriani@gmail.com
Guest
Posts: n/a
 
      12-27-2008
On Dec 25, 8:27*am, James Kanze <(E-Mail Removed)> 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
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
pointer-to-member data and pointer-to-member functions and access specifiers Stephen Howe C++ 2 11-06-2012 12:32 PM
pointer to member function and pointer to constant member function Fraser Ross C++ 4 08-14-2004 06:00 PM
Function pointer member variable to non-member function Alex C++ 0 10-15-2003 05:26 PM
Function pointer member variable to non-member function slide_o_mix C++ 0 10-15-2003 03:37 PM
Passing a pointer to member function as a parameter to another member function Newsgroup - Ann C++ 5 07-30-2003 02:54 AM



Advertisments