I'm trying to learn how to use GTK in C.
I'm developing using Eclipse CDT. I copied the following code from an examples website:
#include <gtk/gtk.h>
#include <stdlib.h>
void displayUI()
{
GtkWidget* mainWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(mainWindow), 400, 300);
gtk_window_set_title(GTK_WINDOW(mainWindow), "GTK Simple Example");
gtk_window_set_position(GTK_WINDOW(mainWindow), GTK_WIN_POS_CENTER_ALWAYS);
gtk_signal_connect(GTK_OBJECT(mainWindow), "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all(mainWindow);
}
int main(int argc, char *argv[]) {
gboolean b = gtk_init_check(&argc, &argv);
if(b == 0) {
puts("Failed to init");
exit(0);
}
gtk_init(&argc, &argv);
displayUI();
gtk_main();
return EXIT_SUCCESS;
}
Every time I try to run this program (or anything else involving GTK, Windows immediately displays a "InsertProgramNameHere.exe has crashed" message.
I have MinGW, MinSYS, PKG-CONFIG and MAKE all properly installed. The program compiles fine... it just won't run.
Any ideas?
UPDATE
I found this error log. There seems to be a dependency problem.
Faulting application TestRun.exe, version 0.0.0.0, time stamp 0x4f839a6a, faulting
module libgtk-win32-2.0-0.dll, version 6.0.6002.18541, time stamp 0x4ec3e39f, exception
code 0xc0000135, fault offset 0x0006f52f, process id 0x1674, application start time
0x01cd16c174d3df90.
exception code 0xc0000135
That is STATUS_DLL_NOT_FOUND. Gtk+ has a large number of dependent DLLs. Probably your best bet to get started is to use the all-in-one bundle and copy the entire content of the bin directory in the archive to your program's EXE directory. Crude but the docs are quite unapologetic about it:
Many of the developer files are relatively irrelevant. If you intend to redistribute the GTK+ run-time, you need to figure out which files you can leave out yourself
Are you sure your GTK installation directory is in your PATH ?
You need to add the path to (MinGW, MinSYS and gtk-dev)'s bin folder in the environment variables.
Related
I'm new to both Linux and C development, trying to take a screenshot in C with the X11 libs.
If I compile and run my program normally, the screenshot is properly taken with no issues. If I run my program as a service, like
sudo systemctl start screenshot
The program fails. Both the logs and analyzing the coredump with GDB only say
Program terminated with signal SIGSEGV, Segmentation fault.
I have set up manual logging in my code:
int main(int argc, char** argv ){
FILE *fp = fopen("log.txt", "w");
setvbuf(fp, NULL, _IONBF, 1024);
fputs("2", fp);
Display* display = XOpenDisplay(NULL);
fputs("5", fp);
Window root = DefaultRootWindow(display);
fputs("6", fp);
When run as a service, log.txt contains the sequence 25. If run from terminal like ./screenshot, the program terminates normally.
Any hints on finding the cause of the issue would be appreciated.
David pointing out to check whether display is NULL and some searching revealed that the issue is that the program can't open the display when running as a service.
Based on this Question: https://unix.stackexchange.com/questions/537628/error-cannot-open-display-on-systemd-service-which-needs-graphical-interface
Setting Environment in the systemd service file as
Environment=DISPLAY=:0.0
Environment=XAUTHORITY=/home/<username>/.Xauthority
resolved the problem and the service runs without issues.
I use the newest GTK+ installed with MSYS2 and whenever I attempt to use
g_application_send_notification() it always results in the following
assert:
(Notification Project.exe:27780): GLib-GObject-CRITICAL **: g_object_new:
assertion 'G_TYPE_IS_OBJECT (object_type)' failed
Why I think it is a bug - because I tried many code samples beside mines
(they are all quite like mines anyway), of people who got it working
(including notifaction by Lars Uebernickel) and it all makes the same
lament.
Assert, followed by crash. Now I really don't know what this means, as it
is probably within gtk internals, but I really hope some of you might have
a clue or experience with this.
install (GNU coreutils) 8.25
GIO version 2.52.3
mingw32/mingw-w64-i686-gtk-engine-unico 1.0.2-2 [installed]
mingw32/mingw-w64-i686-gtk3 3.22.16-1 [installed]
mingw32/mingw-w64-i686-gtkmm3 3.22.0-1 [installed]
mingw32/mingw-w64-i686-spice-gtk 0.33-1 [installed]
mingw32/mingw-w64-i686-webkitgtk3 2.4.11-4 [installed]
mingw64/mingw-w64-x86_64-gtk-engine-unico 1.0.2-2 [installed]
mingw64/mingw-w64-x86_64-gtk3 3.22.16-1 [installed]
mingw64/mingw-w64-x86_64-gtkmm3 3.22.0-1 [installed]
mingw64/mingw-w64-x86_64-spice-gtk 0.33-1 [installed]
mingw64/mingw-w64-x86_64-webkitgtk3 2.4.11-4 [installed]
An example of code that generates this assert:
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gtk/gtk.h>
#define ICON_PATH "/path/trash_16x16.gif"
int main (int argc, char *argv[])
{
GApplication *app;
app = g_application_new ("org.one", G_APPLICATION_FLAGS_NONE);
if(!app)
{
g_print ("Error app\n");
}
else
{
if(g_application_register (app, NULL, NULL))
{
GNotification *notification;
GFile *file;
GIcon *icon;
notification = g_notification_new ("one");
g_notification_set_body (notification, "Hello world");
file = g_file_new_for_path (ICON_PATH);
icon = g_file_icon_new (file);
g_notification_set_icon (notification, G_ICON (icon));
g_application_send_notification (app, NULL, notification);
g_object_unref (icon);
g_object_unref (file);
g_object_unref (notification);
g_object_unref (app);
g_print ("yes\n");
}
else
{
g_print ("no\n");
}
}
return 0;
}
Is that anything I can do to bypass this problem, or perhaps even solve it?
There are no notification backends that work on W32, confirmed. Contributors do wanted, once, to create such, but the API (W32 toast notifications) that is needed is COM-only, and MinGW-w64 doesn't have the necessary headers for it, yet.
Looking at the glib gio source code and GNotificationBackend interface specifically, we can see that it is simple.
Now, you could just do it in GTK...OR we could do it the right way (TM) and implement a D-Bus server for it. The good thing about a notification server is that notifications can persist even after an application is terminated. Also, GTK already has backends for talking to a notification server, so you'd only need to enable these backends on W32 (at a glance, the code doesn't use anything that doesn't work on W32 already). Also, that way the server would transparently use Shell_NotifyIcon (on Windows 7 and earlier) or toast notifications (on Windows 8 and later; if you ever get an opportunity to implement these).
Another option if you want to maintain cross-platformability is to create Shell_NotifyIcon implementation in a DLL and if windows is detected use Shell_NotifyIcon if not, GNotification as you would.
My SDL program contains:
TTF_Init();
TTF_Font *font = TTF_OpenFont("segoeui.ttf",13);
SDL_Color textColor = {0,0,0};
SDL_Color backgroundColor = {34,177,76};
SDL_Surface *myText = TTF_RenderText_Shaded(font,"Some text",textColor,backgroundColor);
When I run the program from the Build and run button in Code::Blocks, there isn't any problem but when I run the program from the folder in Windows Explorer, the window opens and closes directly, and after the window closes, the process isn't running any more and the files stderr.txt and stdout.txt are still there. I've made some tests and found out that it's the line SDL_Surface *myText = TTF_RenderText_Shaded(font,"Some text",textColor,backgroundColor); that seems to end the process just like that like if the End Process button would have been pressed in the task manager.
Why does it do that? How can I fix it?
You should set your font with absolute path and not a relative one. If you plan to do crossplateform deployment, you may want to include something like that:
TTF_Font *font;
#ifdef _WIN32
font = TTF_OpenFont("WinPath",13); // The windows path
#elif linux
font = TTF_OpenFont("LinuxPaht",13); // The linux path
#elif MacOS
font = TTF_OpenFont("Mac path",13); // The mac path
#endif
if(font == null)
// Throw an error, return or whatever.
You can get exact directives at Detect Windows or Linux in C, C++
I am creating my first graphics program in C, using Codeblocks. I am trying to run two graphics loops simultaneously using two threads. One is for keyboard controls and the other is to move a rectangle vertically.
I have been trying to pass a graphics command from ObstacleHandler to the graphics window that main opens, using this condensed bit of code. When I run it, it will just crash as soon as it tries to draw the rectangle. If I initalise a window from the ObstacleHandler and then draw the rectangle, it will be fine. However, I need ObstacleHandler to draw the rectangle in the window that is initalised by the main.
Working example of the issue:
#include <pthread.h>
#include <semaphore.h>
#define NUM_THREADS 2
void *ObstacleHandler(void *threadid)
{
filled_rectangle(100, 120, 100, 120);
update_display();
pthread_exit(NULL);
return 0;
}
int main(int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
long t;
for(t=0;t<NUM_THREADS;t++)
{
printf("In main: creating thread %ld\n", t + 1);
}
pthread_create(&threads[1], NULL, ObstacleHandler, (void *)1);
initwindow(640, 480);
pthread_exit(NULL);
return 0;
}
The window has to be opened using the main function as the keyboard commands are in there. I cannot move them to the ObstacleHandler as that thread will be moving the obstacle.
Also, is there a way that you can have two graphics windows open and each one has a unique identification? I.e graph1 & graph2.
I am using allegro as the graphics library. However, not in the sample code.
I am new to programming so...! Any help would be appreciated!
Thanks
I use Borland/Embarcadero VCL so this could not be your case !!!
but my experience is that if you are accessing any Windows Visual stuff from different then owner window thread then somethings goes terribly wrong in the OS that creates:
visual artifacts
random unrelated crashes
unexpected behavior of the whole Application
this apply for any:
winapi call related to visual components of the window
drawing to window
any access to visual components (like adding line to memo,changing color of something,...)
I code win32 apps and this behavior is present on XP/SP3 x86,W7 x86,W7 x64(WoW64). I did not test different OS versions but suspect this behavior is present also there ...
What to do?
create your global message que
just a list of command you want to support
threads will fill your que
just add appropriate command to que like: redraw window, draw line ...,add to log ...
main window will read and execute it
inside OnTimer or OnIdle event
[Notes]
If you use threads to enhance rendering speed then you should render to thread local bitmap instead and when done add command to copy its contents to target visual component. Do not forget that the que has to be thread safe so add locks to it !!!
I downloaded the lasted stable ruby source code from the ruby website (1.9.2-p180) and compiled it on Windows with MinGW 4.5.2-TDM and MSYS. To compile I ran sh configure and make. I got msvcrt-ruby191.dll and libmsvcrt-ruby191.dll.a exactly as expected. Then I wrote this code:
#include <ruby.h>
int main() {
ruby_init();
rb_funcall2(Qnil, rb_intern("p"), 1, (VALUE[]){INT2FIX(0)});
ruby_finalize();
}
I compiled with g++, linking to the ruby's dll. When I ran the executable, I got this error message:
<main>: [BUG] Segmentation fault
ruby 1.9.2p180 (2011-02-18 revision 30909) [i386-mingw32]
-- control frame ----------
c:0002 p:---- s:0004 b:0004 l:000003 d:000003 CFUNC :p
c:0001 p:0000 s:0002 b:0002 l:00120c d:00120c TOP
---------------------------
-- Ruby level backtrace information ----------------------------------------
ruby:0:in `p'
[NOTE]
You may have encountered a bug in the Ruby interpreter or extension libraries.
Bug reports are welcome.
For details: http://www.ruby-lang.org/bugreport.html
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
The problem is: The same code works perfectly when linked with the ruby 1.8.7. What is wrong here?
Please, try to extend your init to this:
int main(int argc,char *argv[]) {
ruby_sysinit(&argc, &argv);
{
RUBY_INIT_STACK;
ruby_init();
ruby_init_loadpath();
// ... code
ruby_finalize();
}
return 0; //from main()
}
The initialization process was changed between 1.8 and 1.9 versions, so adding a separate nested block { .. } and a RUBY_INIT_STACK macro in the block are needed now.