?

Log in

No account? Create an account

Previous Entry | Next Entry

In my last update to the Tomboy++ port blog entry, I mentioned that a huge hangup was porting the signal trapping from C# to C++. It would have taken less than 5 minutes if it hadn't been for my attempts to keep the code mostly the same structure. Here is the C# code in question:

...
using Mono.Posix;

namespace Tomboy 
{
	public class Tomboy 
	{
	...
	static Syscall.sighandler_t sig_handler;
	...
	static void RegisterSignalHandlers ()
	{
		sig_handler = OnExitSignal;

		// Connect to SIGTERM and SIGQUIT, so we don't lose
		// unsaved notes on exit...
		Syscall.signal ((int) Signals.SIGTERM, sig_handler);
		Syscall.signal ((int) Signals.SIGQUIT, sig_handler);
	}
	...
	static void OnExitSignal (int signal)
	{
		...
	}
}

In plain english: store the reference to the OnExitSignal handler in sig_handler and then tell the Kernel to bind SIGTERM and SIGQUIT to the method pointed to by sig_handler. Seems simple enough, right? Boy was it a pain in the ass in C++.

For whatever reason I had never tried trapping signal handlers in C++. It's actually not all that different from C. The problem is when one wants to bind to a static class member.

Tomboy.h:
...
namespace Tomboy
{

class Tomboy
{
public:
	...
	static void (*sig_handler)(int);
	...
	static void RegisterSignalHandlers ();

	static void OnExitSignal (int signal);
};

...

}
Tomboy.cc
...
void Tomboy::RegisterSignalHandlers ()
{
	void (*sig_handler)(int) = NULL;
	sig_handler = &OnExitSignal;

	// Connect to SIGTERM and SIGQUIT, so we don't lose
	// unsaved notes on exit...
	std::signal (SIGTERM, sig_handler);
	std::signal (SIGQUIT, sig_handler);
}

void Tomboy::OnExitSignal (int signal)
{
	...
}

The thing that kept getting me is needing to first initialize, in a static class method, the function pointer to something. Because the sig_handler is a static variable and NOT an actual static function, it must be initialized in the implementation like a static variable. If I had been able to NOT use a static class method, it would have been a snap. But, as I said, I'm trying to keep the code between the two projects almost exactly the same WRT to structure.

So, anyways, score one point for C# ease of use.

I won't have time to work on the port again until later tonight.

Comments

( 4 comments — Leave a comment )
murraycu
Jul. 26th, 2006 03:24 pm (UTC)
stuff
I was confused at first by the talk of signals and function pointers, but then I relalised that you are talking about Linux/Unix signals, and not GObject/ or ibsigc++ signals.

Anyway:

1. How to initialize a static variable (you should get a linker warning if you don't do this):

The .h file:

class Something
{
public:
Something();

static int somestaticthing;
};l

The .cc file:

int Something::somestaticthing = 0;

Someting::Something()
{}

2. Function pointers:

You can make function pointers much clearer by using typedefs. So you'd have:

.h:

class Tomboy
{
public:
...
typedef void (*type_sig_handler)(int);
static type_sig_handler m_sig_handler;
...
static void RegisterSignalHandlers ();
...
static void OnExitSignal (int signal);
};

.cc:

Tomboy::type_sig_handler Tomboy::m_sig_handler = 0;

void Tomboy::RegisterSignalHandlers ()
{
m_sig_handler = &Tomboy::OnExitSignal;

// Connect to SIGTERM and SIGQUIT, so we don't lose
// unsaved notes on exit...
std::signal (SIGTERM, m_sig_handler);
std::signal (SIGQUIT, m_sig_handler);
}

Of course, I see nothing here that suggests that you need to store a pointer to the signal handler in a local variable. In your example, you are declaring a member variable but not even using it - you redeclare it locally in your function. This is clearer with the typedef.


hub_
Jul. 26th, 2006 06:10 pm (UTC)
I don't even think you need that sig_handler variable. All you need it to pass the pointer to the static function to the std::signal()
jasondclinton
Jul. 26th, 2006 06:20 pm (UTC)
Yes, that's true but, again, I'm copying the Tomboy code directly. If I take a shortcut here, that wouldn't really be a fair basis for comparison.
murraycu
Jul. 27th, 2006 08:01 am (UTC)
Odd
It doesn't seem to be a correct translation then, unless Tomboy is also declaring a variable that it doesn't use.

But maybe (wild speculation alert) Tomboy needs to do this in C#. If it's easier in C++ then shouldn't you take the simpler route to feel the goodness? If it's not necessary in Tomboy then maybe they'd like a cleanup patch.
( 4 comments — Leave a comment )

Profile

color, uphair, smile
jasondclinton
Jason D. Clinton

Latest Month

September 2011
S M T W T F S
    123
45678910
11121314151617
18192021222324
252627282930 

Tags

Powered by LiveJournal.com
Designed by Tiffany Chow