TODO: This is now in Glib, not Gdk. GDK(gtkmmの基礎となるライブラリのひとつ)にあるとても便利な機能のひとつに、ファイル記述子上のデータを自動でチェックしてくれるというものがあります。この機能はとりわけネットワークアプリケーションを作る際に有用です。以下のメソッドが使われます:
sigc::connection Glib::Main::SignalInput::connect(const SlotType& sd, int source,
Glib::InputCondition condition);
最初の引数はスロット(SlotTypeはsigc::slot<>型のtypedef)で、指定されたイベント(第三引数)が、第二引数のファイル記述子上で発生したときに呼ばれます。第三引数は以下の条件のひとつ以上の組み合わせ(|を使う)です:
GDK_INPUT_READ - スロットが呼ばれるのはファイル記述子上でデータが読み込み可能な時です。
GDK_INPUT_WRITE - スロットが呼ばれるのはファイル記述子上で書き込みが可能な時です。
GDK_INPUT_EXCEPTION - スロットが呼ばれるのはファイル記述子上で例外が発生した時です。
返り値はsigc::connectionオブジェクトであり、これはファイル記述子のモニタリングを停止するのに使われます。disconnect()メソッドを使ってください。第一引数のシグナルハンドラsdは以下のように宣言したほうがいいでしょう:
void input_callback(int source, GdkInputCondition condition);
このsourceとconditionは上で説明したものと同じです。普通、スロットはsigc::mem_fun()(オブジェクトのメンバ関数に対して)か、sigc::ptr_fun() (グローバルな関数に対して)で生成します。
短い例が以下にあります。このコード例を使うには端末から実行してください。ウィンドウを生成しないからです。このコードはカレントディレクトリにtestfifoという名前のパイプを生成します。別のシェルを起動して、echo "Hello" > testfifo を実行してください。ユーザーからの入力が一行づつ出力されます。止めるには echo "Q" > testfifo を実行してください。
File: main.cc
#include <gtkmm/main.h>
#include "gtkmmconfig.h" //For HAVE_MKFIFO
#include <fcntl.h>
#include <iostream>
#include <unistd.h> //The SUN Forte compiler puts F_OK here.
//The SUN Forte compiler needs these for mkfifo:
#include <sys/types.h>
#include <sys/stat.h>
int read_fd;
Glib::RefPtr<Glib::IOChannel> iochannel;
/*
send to the fifo with:
echo "Hello" > testfifo
quit the program with:
echo "Q" > testfifo
*/
// this will be our signal handler for read operations
// it will print out the message sent to the fifo
// and quit the program if the message was 'Q'.
bool MyCallback(Glib::IOCondition io_condition)
{
if ((io_condition & Glib::IO_IN) == 0) {
std::cerr << "Invalid fifo response" << std::endl;
}
else {
Glib::ustring buf;
#ifdef GLIBMM_EXCEPTIONS_ENABLED
iochannel->read_line(buf);
#else
std::auto_ptr<Glib::Error> ex;
iochannel->read_line(buf, ex);
if(ex.get())
std::cerr << "Error: " << ex->what() << std::endl;
#endif //GLIBMM_EXCEPTIONS_ENABLED
std::cout << buf;
if (buf == "Q\n")
Gtk::Main::quit ();
}
return true;
}
int main(int argc, char *argv[])
{
// the usual Gtk::Main object
Gtk::Main app(argc, argv);
if (access("testfifo", F_OK) == -1) {
// fifo doesn't exit - create it
#ifdef HAVE_MKFIFO
if (mkfifo("testfifo", 0666) != 0) {
std::cerr << "error creating fifo" << std::endl;
return -1;
}
#else
std::cerr << "error creating fifo: This platform does not have mkfifo()"
<< std::endl;
#endif //HAVE_MKFIFO
}
read_fd = open("testfifo", O_RDONLY);
if (read_fd == -1)
{
std::cerr << "error opening fifo" << std::endl;
return -1;
}
// connect the signal handler
Glib::signal_io().connect(sigc::ptr_fun(MyCallback), read_fd, Glib::IO_IN);
// Creates a iochannel from the file descriptor
iochannel = Glib::IOChannel::create_from_fd(read_fd);
// and last but not least - run the application main loop
app.run();
// now remove the temporary fifo
if(unlink("testfifo"))
std::cerr << "error removing fifo" << std::endl;
return 0;
}