Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > How to play with C callbacks (signal()) using C++ instance methods.

Reply
Thread Tools

How to play with C callbacks (signal()) using C++ instance methods.

 
 
Daniel Koch
Guest
Posts: n/a
 
      11-26-2008
Great people,

I've a doubt about POSIX C functions when I'm using with C++.

I need to handle a signal, the signal() from signal.h needs a
callback. This callback need to perform an action inside class.

How can I define this callback as my instance method?

I think the wrong way is to define a pointer to class instance (this)
as global, then I can call public methods of class from this callback
(the callback defined by signal() haven't a void pointer to pass an
instance pointer).

What's the right way to do this?

Thank you,
Daniel Koch
 
Reply With Quote
 
 
 
 
Maxim Yegorushkin
Guest
Posts: n/a
 
      11-26-2008
On Nov 26, 5:01*pm, Daniel Koch <(E-Mail Removed)> wrote:

> I've a doubt about POSIX C functions when I'm using with C++.
>
> I need to handle a signal, the signal() from signal.h needs a
> callback. This callback need to perform an action inside class.
>
> How can I define this callback as my instance method?
>
> I think the wrong way is to define a pointer to class instance (this)
> as global, then I can call public methods of class from this callback
> (the callback defined by signal() haven't a void pointer to pass an
> instance pointer).


You would need a global object.

> What's the right way to do this?


There is a deeper problem: from within a signal handler you can call
only a limited set of functions, see the complete function list
http://www.opengroup.org/onlinepubs/...l#tag_02_04_03.

Popular functions like malloc() (and C++ new), all C stdio (and C++
IOStreams) and all pthread functions are not async-signal safe.

A standard way to deal with signals is the self-pipe trick, where a
signal handler writes a byte to a pipe whose other end is monitored by
select() in the main program. With new Linux kernels you can do
better: http://www.kernel.org/doc/man-pages/...ignalfd.2.html

This way your signals end up being file descriptor events, which you
can redirect easily to member functions.

Another way is to block signals in all threads and spawn a thread
which would wait for signals using sigwait() and handle signals
synchronously in that thread only.

--
Max

 
Reply With Quote
 
 
 
 
James Kanze
Guest
Posts: n/a
 
      11-26-2008
On Nov 26, 6:01 pm, Daniel Koch <(E-Mail Removed)> wrote:
> I've a doubt about POSIX C functions when I'm using with C++.


> I need to handle a signal, the signal() from signal.h needs a
> callback. This callback need to perform an action inside
> class.


You can't do that from a signal handler, at least not reliably.

> How can I define this callback as my instance method?


You can't.

> I think the wrong way is to define a pointer to class instance
> (this) as global, then I can call public methods of class from
> this callback (the callback defined by signal() haven't a void
> pointer to pass an instance pointer).


Even that's not guaranteed to work. The relevant standards (C,
C++ and Posix) don't even allow you to read a pointer, much less
do anything with it.

> What's the right way to do this?


Do what? The usual way of associating complex actions with a
signal under Posix is to use a signal handling thread, using
sigaction to block the signals in all of the other threads, and
sigwait in the signal handling thread. This should all be
described in your books on Unix programming (and since it is so
Unix specific, if you have further questions, you should ask in
a Unix group).

--
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
 
Daniel Koch
Guest
Posts: n/a
 
      11-26-2008
On 26 nov, 16:24, James Kanze <(E-Mail Removed)> wrote:
> On Nov 26, 6:01 pm, Daniel Koch <(E-Mail Removed)> wrote:
>
> > I've a doubt about POSIX C functions when I'm using with C++.
> > I need to handle a signal, the signal() from signal.h needs a
> > callback. This callback need to perform an action inside
> > class.

>
> You can't do that from a signal handler, at least not reliably.
>
> > How can I define this callback as my instance method?

>
> You can't.
>
> > I think the wrong way is to define a pointer to class instance
> > (this) as global, then I can call public methods of class from
> > this callback (the callback defined by signal() haven't a void
> > pointer to pass an instance pointer).

>
> Even that's not guaranteed to work. *The relevant standards (C,
> C++ and Posix) don't even allow you to read a pointer, much less
> do anything with it.
>
> > What's the right way to do this?

>
> Do what? *The usual way of associating complex actions with a
> signal under Posix is to use a signal handling thread, using
> sigaction to block the signals in all of the other threads, and
> sigwait in the signal handling thread. *This should all be
> described in your books on Unix programming (and since it is so
> Unix specific, if you have further questions, you should ask in
> a Unix group).
>
> --
> 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


I've found Glib::SignalChildWatch.

I'm using gtkmm to show some windows and it is using libsigc++,
now I can use an instance method as signal handlers.

Thank you.
Daniel Koch
 
Reply With Quote
 
Juha Nieminen
Guest
Posts: n/a
 
      11-27-2008
Daniel Koch wrote:
> What's the right way to do this?


Other people have written about it not being standard and not
guaranteed to work and whatever, but I myself have used this many times
with C callbacks in unix systems successfully.

Most C callback mechanisms will take some data pointer as parameter,
which they will then pass to the callback function. Simply give a
pointer to the class instance as this data pointer, and as callback
function create a function which will reinterpret-cast that void* to the
class type and call the proper member function.

For example, assume you have some class like:

class A
{
public:
void callback();
};


You want to create an instance of A, and then have the C library
callback end up calling that A::callbackFunction() for that instance.
What you do is that you write a callback function with a signature
expected by that C library, and inside it you just call the object:

void callbackFunction(void* data)
{
A* obj = reinterpret_cast<A*>(data);
obj->callback();
}

Then somewhere you tell the C library to call that function, like:

cLibrarySetupCallbackFunction(callbackFunction, &obj);

where 'obj' is that A instance which you want to be called.

I have had this work like that. It *might* be possible that in some
situation you'll have to surround that callbackFunction with extern "C".

Sure, there might be *some* architectures and compilers where this
won't work, but I have had it working at least with gcc in a Sparc
Solaris as well as a PC Linux system.
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      11-28-2008
On Nov 27, 11:44 pm, Juha Nieminen <(E-Mail Removed)> wrote:
> Daniel Koch wrote:
> > What's the right way to do this?


> Other people have written about it not being standard and not
> guaranteed to work and whatever, but I myself have used this
> many times with C callbacks in unix systems successfully.


> Most C callback mechanisms will take some data pointer as
> parameter, which they will then pass to the callback function.


Did you read his question? He was concerned doing something
from a signal handler. It's not just any callback; signal
handlers run under very special conditions. And of course, they
*don't* take a data pointer which will be passed back to the
handler.

[...]
> You want to create an instance of A, and then have the C
> library callback end up calling that A::callbackFunction() for
> that instance. What you do is that you write a callback
> function with a signature expected by that C library, and
> inside it you just call the object:


> void callbackFunction(void* data)
> {
> A* obj = reinterpret_cast<A*>(data);
> obj->callback();
> }


> Then somewhere you tell the C library to call that function, like:
>
> cLibrarySetupCallbackFunction(callbackFunction, &obj);


> where 'obj' is that A instance which you want to be called.


This is fine for most callbacks, except that you have to declare
callbackFunction ``extern "C"''.

> I have had this work like that. It *might* be possible that in
> some situation you'll have to surround that callbackFunction
> with extern "C".


The "situation" where you'd have to use ``extern "C"'' is
simple: any time the compiler isn't broken.

> Sure, there might be *some* architectures and compilers where
> this won't work, but I have had it working at least with gcc
> in a Sparc Solaris as well as a PC Linux system.


This is a known bug in g++. Sun CC will diagnose an error
without the ``extern "C"''.

--
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
 
Maxim Yegorushkin
Guest
Posts: n/a
 
      11-28-2008
On Nov 27, 10:44*pm, Juha Nieminen <(E-Mail Removed)> wrote:
> Daniel Koch wrote:
> > What's the right way to do this?

>
> * Other people have written about it not being standard and not
> guaranteed to work and whatever, but I myself have used this many times
> with C callbacks in unix systems successfully.
>
> * Most C callback mechanisms will take some data pointer as parameter,
> which they will then pass to the callback function. Simply give a
> pointer to the class instance as this data pointer, and as callback
> function create a function which will reinterpret-cast that void* to the
> class type and call the proper member function.


static_cast<> is sufficient when casting from void* to T*.

--
Max
 
Reply With Quote
 
Maxim Yegorushkin
Guest
Posts: n/a
 
      11-28-2008
On Nov 28, 8:32*am, James Kanze <(E-Mail Removed)> wrote:
> On Nov 27, 11:44 pm, Juha Nieminen <(E-Mail Removed)> wrote:


[]

> > cLibrarySetupCallbackFunction(callbackFunction, &obj);
> > where 'obj' is that A instance which you want to be called.

>
> This is fine for most callbacks, except that you have to declare
> callbackFunction ``extern "C"''.
>
> > I have had this work like that. It *might* be possible that in
> > some situation you'll have to surround that callbackFunction
> > with extern "C".

>
> The "situation" where you'd have to use ``extern "C"'' is
> simple: any time the compiler isn't broken.
>
> > Sure, there might be *some* architectures and compilers where
> > this won't work, but I have had it working at least with gcc
> > in a Sparc Solaris as well as a PC Linux system.

>
> This is a known bug in g++. *Sun CC will diagnose an error
> without the ``extern "C"''.


C and C++ calling conventions have been the same on Solaris. I don't
think Sun will ever change it because their remaining customers are
not going to be happy.

While formally it might make sense to emit this error, it is
practically useless.

--
Max

 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      11-28-2008
On Nov 28, 10:42 am, Maxim Yegorushkin <(E-Mail Removed)>
wrote:
> On Nov 28, 8:32 am, James Kanze <(E-Mail Removed)> wrote:


[...]
> C and C++ calling conventions have been the same on Solaris. I
> don't think Sun will ever change it because their remaining
> customers are not going to be happy.


> While formally it might make sense to emit this error, it is
> practically useless.


It's required by the standard. A compiler which doesn't emit
the error isn't conform. The fact that the calling conventions
happen to be the same isn't really relevant; the language allows
them to be different, and considers them different types.

--
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
 
Maxim Yegorushkin
Guest
Posts: n/a
 
      11-28-2008
On Nov 28, 2:25*pm, James Kanze <(E-Mail Removed)> wrote:
> On Nov 28, 10:42 am, Maxim Yegorushkin <(E-Mail Removed)>
> wrote:
>
> > On Nov 28, 8:32 am, James Kanze <(E-Mail Removed)> wrote:

>
> * * [...]
>
> > C and C++ calling conventions have been the same on Solaris. I
> > don't think Sun will ever change it because their remaining
> > customers are not going to be happy.
> > While formally it might make sense to emit this error, it is
> > practically useless.

>
> It's required by the standard. *A compiler which doesn't emit
> the error isn't conform. *The fact that the calling conventions
> happen to be the same isn't really relevant; the language allows
> them to be different, and considers them different types.


Is there a platform/compiler where they are different?

--
Max
 
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
Re: How include a large array? Edward A. Falk C Programming 1 04-04-2013 08:07 PM
To play or not to play bhuckle@bigpond.net.au DVD Video 1 08-01-2007 07:18 AM
PLAY MORE VIDEO GAMES WITH GOTTA PLAY Paul Heslop Digital Photography 0 05-21-2007 11:40 AM
instance based callbacks johny smith C++ 2 05-14-2004 04:04 AM



Advertisments