Παράδειγμα δεκτών και δοτών (Plugs and Sockets)

Το παρακάτω είναι ένα απλό παράδειγμα χρήσης δεκτών και δοτών. Η μέθοδος επικοινωνίας μεταξύ διεργασιών διατηρείται σκόπιμα πολύ απλή: Η Plug γράφει το αναγνωριστικό της σε ένα αρχείο κειμένου με όνομα plug.id και η επεξεργασία με τον δέκτη διαβάζει το αναγνωριστικό από αυτό το αρχείο. Σε ένα πραγματικό πρόγραμμα, μπορεί να θέλετε να χρησιμοποιήσετε μια περισσότερο προηγμένη μέθοδο επικοινωνίας μεταξύ των διεργασιών.

Source Code

File: plug.cc (For use with gtkmm 3, not gtkmm 2)

#include <iostream>
#include <fstream>
#include <gtkmm.h>
#include <gtkmm/plug.h>
#include <glib/gstdio.h>

using namespace std;

const char* id_filename = "plug.id";

void on_embed()
{
  cout << "I've been embedded." << endl;
}

class MyPlug : public Gtk::Plug
{
  public:
    MyPlug() :
      m_label("I am the plug")
  {
    set_size_request(150, 100);
    add(m_label);
    signal_embedded().connect(sigc::ptr_fun(on_embed));
    show_all_children();
  }

  private:
    Gtk::Label m_label;
};


int main(int argc, char** argv)
{
  // The plug and the socket have different application ids, so they can run
  // simultaneously.
  auto app =
    Gtk::Application::create(argc, argv, "org.gtkmm.example.plug");
  MyPlug plug;
  plug.show();

  ofstream out(id_filename);
  out << plug.get_id();
  out.close();
  cout << "The window ID is: " << plug.get_id() << endl;

  app->run(plug);

  // remove the ID file when the program exits
  g_remove(id_filename);
  return 0;
}

File: socket.cc (For use with gtkmm 3, not gtkmm 2)

#include <iostream>
#include <fstream>
#include <gtkmm.h>
#include <gtkmm/socket.h>

using namespace std;

const char* id_filename = "plug.id";

void plug_added()
{
  cout << "A plug was added" << endl;
}

bool plug_removed()
{
  cout << "A Plug was removed" << endl;
  return true;
}

class MySocketWindow : public Gtk::Window
{
  public:
    MySocketWindow()
    {
      ifstream infile(id_filename);
      if (infile)
      {
        auto socket = Gtk::manage(new Gtk::Socket());
        add(*socket);
        socket->signal_plug_added().connect(sigc::ptr_fun(plug_added));
        socket->signal_plug_removed().connect(sigc::ptr_fun(plug_removed));
        ::Window plug_id = 0;
        infile >> plug_id;
        infile.close();
        socket->add_id(plug_id);
      }
      else
      {
        auto label = Gtk::manage(
            new Gtk::Label(
              "Plug id file not found.\n Make sure plug is running."));
        add(*label);
        set_size_request(150, 50);
      }
      show_all();
    }
};

int main(int argc, char** argv)
{
  // The plug and the socket have different application ids, so they can run
  // simultaneously.
  auto app =
    Gtk::Application::create(argc, argv, "org.gtkmm.example.socket");
  MySocketWindow win;
  app->run(win);
  return 0;
}

Αυτό το παράδειγμα δημιουργεί δύο εκτελέσιμα προγράμματα: socket και plug. Η ιδέα είναι ότι η socket έχει ένα παράθυρο εφαρμογής που θα ενσωματώσει ένα γραφικό συστατικό από το πρόγραμμα plug. Ο τρόπος αυτού του παραδείγματος σχεδιάστηκε έτσι ώστε το plug να πρέπει να εκτελεστεί πρώτα πριν ξεκινήσει το socket. Για να δείτε το παράδειγμα σε δράση, εκτελέστε τις παρακάτω εντολές με τη σειρά μέσα στον κατάλογο του παραδείγματος:

Ξεκινήστε το πρόγραμμα plug και στείλτε το στο παρασκήνιο (ή απλά χρησιμοποιήστε ένα διαφορετικό τερματικό).

$ ./plug &

Μετά από το οποίο θα πρέπει να δείτε κάτι όπως το παρακάτω:

Το αναγνωριστικό του παραθύρου είναι: 69206019

Έπειτα αρχίστε το πρόγραμμα socket:

$ ./socket

Μετά την έναρξη του socket, θα πρέπει να δείτε την παρακάτω έξοδο στο τερματικό:

I've been embedded.
A plug was added

Η πρώτη γραμμή της εξόδου είναι από το plug, αφού έχει ειδοποιηθεί ότι έχει ενσωματωθεί μέσα σε μια Socket. Η δεύτερη γραμμή εκπέμφθηκε από το socket σε απάντηση του σήματός του plug_added. Αν όλα έγιναν όπως περιγράφτηκε παραπάνω, το παράθυρο socket πρέπει να φαίνεται χοντρικά όπως το παρακάτω:

If for some reason the Socket couldn't attach the Plug, the window would look something like this: