Требовалось сделать аналог виндовой функции MessageBox исключительно для вывода сообщений об ошибках.
Решил динамически грузить GTK-ашную либу и минимальным количеством её функций выводить требуемое.
Вот что получилось:
#include <stdlib.h>
#include <stdio.h>
#ifdef __unix__
#include <dlfcn.h>
#endif /* __unix__ */
void error_msg_box(const char *msg);
int main() {
error_msg_box("Test ok.");
return EXIT_SUCCESS;
}
void error_msg_box(const char *msg) {
if (msg == NULL)
msg = "Unknown error.";
#ifdef _WIN32
int __stdcall MessageBoxA
(void *wnd, const char *text, const char *caption, unsigned int type);
#define MB_ICONERROR 0x10
MessageBoxA(NULL, msg, "Error", MB_ICONERROR);
#else
#ifdef __unix__
void *lib_gtk = dlopen("libgtk-x11-2.0.so", RTLD_LAZY);
if (lib_gtk == NULL)
goto fb;
typedef void (*GTK_INIT)(int *argc, char ***argv);
typedef void *(*GTK_MESSAGE_DIALOG_NEW)(void *parent, int flags, int type, int buttons, const char *format, ...);
typedef void (*GTK_WINDOW_SET_TITLE)(void *window, const char *title);
typedef void (*GTK_WINDOW_SET_POSITION)(void *window, int position);
typedef void (*GTK_WINDOW_SET_KEEP_ABOVE)(void *window, int setting);
typedef int (*GTK_DIALOG_RUN)(void *dialog);
typedef void (*GTK_WIDGET_DESTROY)(void *widget);
GTK_INIT gtk_init;
GTK_MESSAGE_DIALOG_NEW gtk_message_dialog_new;
GTK_WINDOW_SET_TITLE gtk_window_set_title;
GTK_WINDOW_SET_POSITION gtk_window_set_position;
GTK_WINDOW_SET_KEEP_ABOVE gtk_window_set_keep_above;
GTK_DIALOG_RUN gtk_dialog_run;
GTK_WIDGET_DESTROY gtk_widget_destroy;
#define GTK_MESSAGE_ERROR 3
#define GTK_BUTTONS_CLOSE 2
#define GTK_WIN_POS_CENTER 1
if (
!(gtk_init = dlsym(lib_gtk, "gtk_init")) ||
!(gtk_message_dialog_new = dlsym(lib_gtk, "gtk_message_dialog_new")) ||
!(gtk_window_set_title = dlsym(lib_gtk, "gtk_window_set_title")) ||
!(gtk_window_set_position = dlsym(lib_gtk, "gtk_window_set_position")) ||
!(gtk_window_set_keep_above = dlsym(lib_gtk, "gtk_window_set_keep_above")) ||
!(gtk_dialog_run = dlsym(lib_gtk, "gtk_dialog_run")) ||
!(gtk_widget_destroy = dlsym(lib_gtk, "gtk_widget_destroy"))
)
goto fb;
gtk_init(NULL, NULL);
void *dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", msg);
gtk_window_set_title(dialog, "Error");
gtk_window_set_position(dialog, GTK_WIN_POS_CENTER);
gtk_window_set_keep_above(dialog, 1);
gtk_dialog_run(dialog);
gtk_widget_destroy(dialog);
if (dlclose(lib_gtk))
fputs("Warning: Failed to close GTK library.\n", stderr);
return;
#endif /* __unix__ */
fb: fprintf(stderr, "Error: %s\n", msg);
#endif /* _WIN32 */
}
gcc main.c -ldl -o main
(Под винду так:
i686-w64-mingw32-gcc main.c -o main.exe
)Внимание вопрос: зачем в GTK нужны макросы GTK_DIALOG(obj), GTK_WINDOW(obj) и т.п. если всё вроде как работает и без них?
В документации в эти макросы предлагают оборачивать объекты (виджеты) при передаче в функции, например так:
gtk_dialog_run(GTK_DIALOG(dialog));