GTK Hello World complains about undefined references - c

I'm using Linux Mint 20 to learn GTK. I installed the following package to get started:
sudo apt-get install build-essential libgtk-3-dev
And then proceeded to compile the Hello World app in C:
#include <gtk/gtk.h>
static void
print_hello (GtkWidget *widget,
gpointer data)
{
g_print ("Hello World\n");
}
static void
activate (GtkApplication *app,
gpointer user_data)
{
GtkWidget *window;
GtkWidget *button;
GtkWidget *button_box;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
button_box = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
gtk_container_add (GTK_CONTAINER (window), button_box);
button = gtk_button_new_with_label ("Hello World");
g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_window_close), window);
gtk_container_add (GTK_CONTAINER (button_box), button);
gtk_widget_show_all (window);
}
int
main (int argc,
char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}
As the example requests, I compiled it using:
gcc `pkg-config --cflags gtk+-3.0` -o hello-world-gtk hello-world-gtk.c `pkg-config --libs gtk+-3.0`
But it didn't work, and I have no idea why. It's output was:
/usr/bin/ld: /usr/lib/x86_64-linux-gnu/libwayland-client.so.0: referência não definida para "ffi_type_void#LIBFFI_BASE_7.0"
/usr/bin/ld: /usr/lib/x86_64-linux-gnu/libwayland-client.so.0: referência não definida para "ffi_call#LIBFFI_BASE_7.0"
/usr/bin/ld: /usr/lib/x86_64-linux-gnu/libwayland-client.so.0: referência não definida para "ffi_type_uint32#LIBFFI_BASE_7.0"
/usr/bin/ld: /usr/lib/x86_64-linux-gnu/libwayland-client.so.0: referência não definida para "ffi_type_sint32#LIBFFI_BASE_7.0"
/usr/bin/ld: /usr/lib/x86_64-linux-gnu/libwayland-client.so.0: referência não definida para "ffi_prep_cif#LIBFFI_BASE_7.0"
/usr/bin/ld: /usr/lib/x86_64-linux-gnu/libwayland-client.so.0: referência não definida para "ffi_type_pointer#LIBFFI_BASE_7.0"
collect2: error: ld returned 1 exit status
The "referência não definida para" is Portuguese to something like "undefined reference for".
Anyone knows what I need to do?

I've managed it! The thing is, for some reason my system missed libffi. I downloaded it's latest version, and just installed it:
./configure
(...)
make
(...)
sudo make install
(...)
I've compiled it, and it worked!

Related

Unable to compile GTK4 on Fedora with Hello World example Despite having all the requisite packages

I have read the install instructions on GTK for GTK4, which I used
sudo dnf install gtk4 gtk4-devel
The code of the Hello, World example is
#include <gtk/gtk.h>
static void
print_hello (GtkWidget *widget,
gpointer data)
{
g_print ("Hello World\n");
}
static void
activate (GtkApplication *app,
gpointer user_data)
{
GtkWidget *window;
GtkWidget *button;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
button = gtk_button_new_with_label ("Hello World");
g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
gtk_window_set_child (GTK_WINDOW (window), button);
gtk_window_present (GTK_WINDOW (window));
}
int
main (int argc,
char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}
I used the compile function for GCC:
gcc -o hello-world-gtk hello-world-gtk.c `pkg-config --cflags --libs gtk4`
But this error presents
gtktest.c:1:10: fatal error: gtk/gtk.h: No such file or directory
1 | #include <gtk/gtk.h>
| ^~~~~~~~~~~
As I see, I should have all the requisite packages installed and I am unsure why the compiler cannot pull the gtk library. Any help would be awesome.
Alright I found a strange solution.
For whatever reason, this did not work using their pasted compile code, however when I switched to the below, it worked just fine.
gcc `pkg-config --cflags gtk4` hello.c -o hello `pkg-config --libs gtk4`

compiling gtk3 app for windows in linux using mingw64

I need to compile a simple gtk application for windows using Linux. Here is an example from this link. The compilation via gcc $(pkg-config --cflags gtk+-3.0) -o example-1 example-1.c $(pkg-config --libs gtk+-3.0) works as expected. I installed mingw64 packages for Linux in order to compile for windows.
When I run x86_64-w64-mingw32-gcc $(pkg-config --cflags gtk+-3.0) -o example-1.exe example-1.c $(pkg-config --libs gtk+-3.0) command, I will get this error:
amb#localhost test]$ x86_64-w64-mingw32-gcc $(pkg-config --cflags gtk+-3.0) -o example-1.exe example-1.c $(pkg-config --libs gtk+-3.0)
In file included from /usr/lib64/glib-2.0/include/glibconfig.h:9,
from /usr/include/glib-2.0/glib/gtypes.h:32,
from /usr/include/glib-2.0/glib/galloca.h:32,
from /usr/include/glib-2.0/glib.h:30,
from /usr/include/gtk-3.0/gdk/gdkconfig.h:13,
from /usr/include/gtk-3.0/gdk/gdk.h:30,
from /usr/include/gtk-3.0/gtk/gtk.h:30,
from example-1.c:1:
/usr/include/glib-2.0/glib/gtypes.h: In function '_GLIB_CHECKED_ADD_U64':
/usr/include/glib-2.0/glib/gmacros.h:277:53: error: size of array '_GStaticAssertCompileTimeAssertion_0' is negative
#define G_STATIC_ASSERT(expr) typedef char G_PASTE (_GStaticAssertCompileTimeAssertion_, __COUNTER__)[(expr) ? 1 : -1] G_GNUC_UNUSED
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/glib-2.0/glib/gmacros.h:274:47: note: in definition of macro 'G_PASTE_ARGS'
#define G_PASTE_ARGS(identifier1,identifier2) identifier1 ## identifier2
^~~~~~~~~~~
/usr/include/glib-2.0/glib/gmacros.h:277:44: note: in expansion of macro 'G_PASTE'
#define G_STATIC_ASSERT(expr) typedef char G_PASTE (_GStaticAssertCompileTimeAssertion_, __COUNTER__)[(expr) ? 1 : -1] G_GNUC_UNUSED
^~~~~~~
/usr/include/glib-2.0/glib/gtypes.h:423:3: note: in expansion of macro 'G_STATIC_ASSERT'
G_STATIC_ASSERT(sizeof (unsigned long long) == sizeof (guint64));
^~~~~~~~~~~~~~~
In file included from /usr/include/glib-2.0/gio/gio.h:46,
from /usr/include/gtk-3.0/gdk/gdkapplaunchcontext.h:28,
from /usr/include/gtk-3.0/gdk/gdk.h:32,
from /usr/include/gtk-3.0/gtk/gtk.h:30,
from example-1.c:1:
/usr/include/glib-2.0/gio/gcredentials.h: At top level:
/usr/include/glib-2.0/gio/gcredentials.h:75:1: error: unknown type name 'uid_t'
uid_t g_credentials_get_unix_user (GCredentials *credentials,
^~~~~
/usr/include/glib-2.0/gio/gcredentials.h:79:52: error: unknown type name 'uid_t'; did you mean 'pid_t'?
uid_t uid,
^~~~~
pid_t
I'm new to programming with C and cross compilation. Please explain this problem and provide a solution for me. thx
this is the code (example-1.c):
#include <gtk/gtk.h>
static void
print_hello (GtkWidget *widget,
gpointer data)
{
g_print ("Hello World\n");
}
static void
activate (GtkApplication *app,
gpointer user_data)
{
GtkWidget *window;
GtkWidget *button;
GtkWidget *button_box;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
button_box = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
gtk_container_add (GTK_CONTAINER (window), button_box);
button = gtk_button_new_with_label ("Hello World");
g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_widget_destroy), window);
gtk_container_add (GTK_CONTAINER (button_box), button);
gtk_widget_show_all (window);
}
int
main (int argc,
char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}

Compilation errors when using GTK2+ with OpenGL?

I am writing a C program that makes use of fixed pipeline OpenGL and FreeGLUT. However, I would like to use a complete toolkit like GTK+ instead of FreeGLUT. I cannot use GTK3+ as it is not compatible with old OpenGL code, so I would like to use GTK2+.
I found this link with an example program called simple.c:
#include <math.h>
#include <gtk/gtk.h>
#include <GL/gl.h>
#include <gtkgl/gtkglarea.h>
int init (GtkWidget *widget)
{
if (gtk_gl_area_make_current (GTK_GL_AREA(widget)))
{
glViewport(0,0, widget->allocation.width, widget->allocation.height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,100, 100,0, -1,1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
return TRUE;
}
int draw (GtkWidget *widget, GdkEventExpose *event)
{
if (event->count > 0) return TRUE;
if (gtk_gl_area_make_current (GTK_GL_AREA(widget)))
{
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1,1,1);
glBegin(GL_TRIANGLES);
glVertex2f(10,10);
glVertex2f(10,90);
glVertex2f(90,90);
glEnd();
gtk_gl_area_swap_buffers (GTK_GL_AREA(widget));
}
return TRUE;
}
int reshape (GtkWidget *widget, GdkEventConfigure *event)
{
if (gtk_gl_area_make_current (GTK_GL_AREA(widget)))
glViewport(0,0, widget->allocation.width, widget->allocation.height);
return TRUE;
}
int main (int argc, char **argv)
{
GtkWidget *window, *glarea;
int attrlist[] = {
GDK_GL_RGBA,
GDK_GL_RED_SIZE,1,
GDK_GL_GREEN_SIZE,1,
GDK_GL_BLUE_SIZE,1,
GDK_GL_DOUBLEBUFFER,
GDK_GL_NONE };
gtk_init (&argc, &argv);
if (gdk_gl_query () == FALSE) return 0;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW(window), "Simple");
gtk_container_set_border_width (GTK_CONTAINER(window), 10);
g_signal_connect (window, "delete_event",
G_CALLBACK (gtk_main_quit), NULL);
/* You should always delete gtk_gl_area widgets before exit or else
GLX contexts are left undeleted, this may cause problems (=core dump)
in some systems.
Destroy method of objects is not automatically called on exit.
You need to manually enable this feature. Do gtk_quit_add_destroy()
for all your top level windows unless you are certain that they get
destroy signal by other means. */
gtk_quit_add_destroy (1, GTK_OBJECT(window));
glarea = GTK_WIDGET(gtk_gl_area_new (attrlist));
gtk_widget_set_size_request (GTK_WIDGET(glarea), 100, 100);
gtk_widget_set_events (GTK_WIDGET(glarea), GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK);
g_signal_connect (glarea, "expose_event", G_CALLBACK(draw), NULL);
g_signal_connect (glarea, "configure_event", G_CALLBACK(reshape), NULL);
g_signal_connect (glarea, "realize", G_CALLBACK(init), NULL);
gtk_container_add (GTK_CONTAINER(window), GTK_WIDGET(glarea));
gtk_widget_show (GTK_WIDGET(glarea));
gtk_widget_show (GTK_WIDGET(window));
gtk_main ();
return 0;
}
but unfortunately it requeries a file that I don't know where to get, gtk_opengl.h
I unsuccessfully tried to compile this simple.c code with
gcc simple.c -o helloworld `pkg-config --libs gtk+-2.0`
and, of course, got the following error:
fatal error: gtk_opengl.h: No such file or directory
Any ideas on how to make simple.c compile? Or on how to combine OpenGL with GTK2+?
On my Debian Stable box I had to install libgtkgl2.0-dev and add --cflags & gtkgl-2.0 to the pkg-config invocation:
gcc simple.c -o helloworld `pkg-config --cflags --libs gtk+-2.0 gtkgl-2.0`

GTK Basic Window App on Mac - Warning, Deprecated

I'm running a basic GTK app from the GTK website's tutorials, and I'm getting the following warning:-
*** WARNING: Method userSpaceScaleFactor in class NSView is deprecated on 10.7 and later. It should not be used in new applications. Use convertRectToBacking: instead.
I've installed the gtk+ and gtk+3 packages with brew. Here is the code from the file:-
#include
static void
activate (GtkApplication* app,
gpointer user_data)
{
GtkWidget *window;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
gtk_widget_show_all (window);
}
int
main (int argc,
char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}
I'm running OS X 10.10.5, MacBook Pro 13in Retina.
Any ideas? Thanks!

GTK Application crashes when I try to call GtkWidget object in other Thread

I have pretty simple application with text entry and button.
When user press on button , the application downloads file (in other thread) from URL and on success opens dialog message that all done. During downloading i activate spinner (like busy)
Since I don't know how long will take connect to download file I use separate thread for that purpose. But on "dialog show" my application fails and I get followed error:
(enter_license.exe:210232): Gdk-WARNING **: gdkdrawable-win32.c:1873: GetDC failed: Invalid window handle.
(enter_license.exe:210232): Gdk-WARNING **: gdkgc-win32.c:968: GetCurrentObject failed: The handle is invalid.
(enter_license.exe:210232): Gdk-WARNING **: gdkgc-win32.c:970: RestoreDC failed: The handle is invalid.
(enter_license.exe:210232): Gdk-CRITICAL **: _gdk_win32_drawable_release_dc: assertion `impl->hdc_count > 0' failed
(enter_license.exe:210232): Gdk-WARNING **: gdkwindow-win32.c:2216: SetWindowLongPtr failed: Invalid window handle.
Sounds like something wrong when I try to call GTK object from separate thread.
Maybe somehow I need call handle (callback) to implement "show_dialog" in main thread?
Compile:
gcc -IC:/MinGW/include -o enter_license enter_license.c `pkg-config --libs --cflags gtk+-2.0 gthread-2.0``
Flow: main -> call "do_something" -> create thread and call "argument_thread" ->
Here is a snippets of code:
typedef struct _Data
{
GtkWidget *win;
} Data;
main
int main(int argc, char **argv)
{
GtkWidget *window;
gtk_init(&argc, &argv);
window = do_something(NULL, argv);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_main();
return 0;
}
do_something
GtkWidget * do_something(GtkWidget *do_widget, char **argv){
....
GtkWidget *window;
if (!window){
window = gtk_dialog_new_with_buttons ("GtkSpinner",
GTK_WINDOW (do_widget),
0,
GTK_STOCK_CLOSE,
GTK_RESPONSE_NONE,
NULL);
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
g_signal_connect (window, "response", G_CALLBACK (gtk_widget_destroy), NULL);
g_signal_connect (window, "destroy", G_CALLBACK (gtk_widget_destroyed), &window);
....
if (!gtk_widget_get_visible (window)){
gtk_widget_show_all (window);
}
else{
gtk_widget_destroy (window);
}
// define thread
GThread* thread;
GError* err;
Data data;
data.win = window;
thread = g_thread_create((GThreadFunc)argument_thread,&data,FALSE, &err);
return window;
}
show_dialog
gboolean show_dialog( GtkWidget* mw)
{
GtkWidget *dialog;
printf("BOO: \n");
// here all works fine
sleep(3000);
gtk_widget_show(spinner_sensitive);
gtk_spinner_start (GTK_SPINNER (spinner_sensitive));
sleep(3000);
gtk_spinner_stop (GTK_SPINNER (spinner_sensitive));
sleep(3000);
gtk_widget_hide(spinner_sensitive);
printf("BOO\n");
// here dialog is shown for 1-10 milisec and get error.
dialog = gtk_message_dialog_new (GTK_WINDOW(mw),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_CLOSE,
"Downloaded successfully");
g_signal_connect_swapped (G_OBJECT (dialog), "response",
G_CALLBACK (gtk_widget_destroy),
G_OBJECT (dialog));
gtk_widget_show(dialog);
printf("BOO\n");
}
argument_thread
void *argument_thread( gpointer ptr ) {
Data *data = (Data*)ptr;
gdk_threads_enter();
show_dialog (data->win);
gdk_threads_leave();
return( NULL );
}
Please help me,
Any and all suggestions would be greatly appreciated
GTK is not thread-safe so anything that interacts with the GUI will have to run on the main thread.
Use the g_idle_add function to notify your main thread when the download has finished.
According to #VincentPovirk just for guys who looking for answer, here is a working implementation:
into the Thread we call g_idle_add and call callback_func that will be implemented outside of second Thread (aka in main):
gboolean show_dialog( GtkWidget* mw)
{
sleep(3000);
gtk_widget_show(spinner_sensitive);
gtk_spinner_start (GTK_SPINNER (spinner_sensitive));
sleep(3000);
gtk_spinner_stop (GTK_SPINNER (spinner_sensitive));
gtk_widget_hide(spinner_sensitive);
g_idle_add(callback_func, NULL);
}
gint callback_func(void *unused)
{
GtkWidget *dialog;
dialog = gtk_message_dialog_new (GTK_WINDOW(window),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_CLOSE,
"Succeeded.");
g_signal_connect_swapped (G_OBJECT (dialog), "response",
G_CALLBACK (gtk_widget_destroy),
G_OBJECT (dialog));
gtk_widget_show(dialog);
return FALSE;
}

Resources