Учусь писать на Gtk и ZeroMQ одновременно. В данный момент код ужасен чуть более, чем полностью, однако есть вещь, которая меня интересует более остальных. При использовании обоих библиотек функциям-обработчикам событий надо передавать некоторые ресурсы, такие как, например, контекст и сокеты от ZeroMQ. В связи с этим появились три структуры-обертки для передачи этих параметров. Мне это кажется очень уродливым и хотелось бы узнать нормальное решение. (Почему-то очевидное «сделать глобальные статические ресурсы» кажется мне не менее уродливым) Заранее спасибо за помощь =)
#include <gtk/gtk.h>
#include <zmq.h>
#include <stdlib.h>
#include <string.h>
#define BOX_SPACING 5
typedef struct
{
GtkWidget *widget[5];
} WidgetSet;
typedef struct
{
void *res[5];
} ZMQResourcesSet;
typedef struct
{
WidgetSet * controls;
ZMQResourcesSet * zmq;
} ResList;
static gboolean deleteEvent(GtkWidget *widget, gpointer data)
{
return FALSE;
}
static void destroyEvent (GtkWidget *widget, gpointer data)
{
ZMQResourcesSet t = *((ZMQResourcesSet *)data);
zmq_close(t.res[1]);
zmq_term(t.res[0]);
gtk_main_quit();
}
static void buttonClicked (GtkObject *widget, gpointer data)
{
WidgetSet IOControls = *(((ResList*)data)->controls);
ZMQResourcesSet zmqRes = *(((ResList*)data)->zmq);
void * context = zmqRes.res[0];
void * sender = zmqRes.res[1];
zmq_msg_t request, reply;
int replyLen;
char *answ, *text = gtk_entry_get_text((struct GtkEntry*)(IOControls.widget[1]));
/*Send a message to server*/
zmq_msg_init_size(&request, strlen(text));
memcpy(zmq_msg_data(&request), text, strlen(text));
zmq_send(sender, &request, 0);
zmq_msg_close(&request);
/*Recieve a reply from server*/
zmq_msg_init(&reply);
zmq_recv(sender, &reply, 0);
replyLen = zmq_msg_size(&reply);
answ = malloc (sizeof(char*)*(replyLen + 1));
memcpy(answ, zmq_msg_data(&reply), replyLen);
zmq_msg_close(&reply);
answ[replyLen] = '\0';
/*Change label text*/
gtk_label_set_text((struct GtkLabel*)(IOControls.widget[0]), answ);
}
int main(int argc, char ** argv)
{
GtkWidget *window;
GtkWidget *label, *button, *textEntry, *vbox, *hbox;
WidgetSet IOControls;
void *context, *sender;
ZMQResourcesSet ZmqRes;
ResList reses = {&IOControls, &ZmqRes};
gtk_init (&argc, &argv);
context = zmq_init(1);
/*Socket*/
sender = zmq_socket(context, ZMQ_REQ);
zmq_connect(sender, "tcp://localhost:5555");
ZmqRes.res[0] = context;
ZmqRes.res[1] = sender;
/*Window*/
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (window, "delete_event", G_CALLBACK(deleteEvent), NULL);
g_signal_connect (window, "destroy_event", G_CALLBACK(destroyEvent), (gpointer)&ZmqRes);
/*Label (main text area)*/
label = gtk_label_new("Some text");
/*Text Entrie*/
textEntry = gtk_entry_new();
/*Button*/
button = gtk_button_new_with_label("OK");
IOControls.widget[0] = label;
IOControls.widget[1] = textEntry;
g_signal_connect(button, "clicked", G_CALLBACK(buttonClicked), (gpointer)&reses);
/*Widgets packing*/
vbox = gtk_vbox_new (FALSE, BOX_SPACING);
hbox = gtk_hbox_new (FALSE, BOX_SPACING);
gtk_box_pack_start(GTK_BOX(hbox), textEntry, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
gtk_container_add(GTK_CONTAINER(window), vbox);
/*Finaly let us show widgets*/
gtk_widget_show (label);
gtk_widget_show (button);
gtk_widget_show (textEntry);
gtk_widget_show (hbox);
gtk_widget_show (vbox);
gtk_widget_show (window);
gtk_main ();
return 0;
}