Probleme with structure, string anf gtkwidget - c

I'm trying to create a diaporama in c using gtk. I have a button "previous", which show the previous image. So I connect my button to a function and I pass it to a structure. But when I try to print an element of my array I have weird characters, and I don't know why. Plus, I got this warning for my gtk image :
GLib-GObject-WARNING **: 19:12:16.442: invalid uninstantiatable type '(null)' in cast to 'GtkImage'
Gtk-CRITICAL **: 19:12:16.442: IA__gtk_image_set_from_file: assertion 'GTK_IS_IMAGE (image)' failed
Here's my structure :
struct ButtonsArg {
GtkWidget *image;
char *img[];
};
Here's my code for the initialisation of my structure in the main :
GtkWidget *image = gtk_image_new();
char *images[nbImages];
//I get the name of all my image in this function
getImageList(images);
//This print work fine
printf("%s\n", images[0]);
struct ButtonsArg * arg;
arg = malloc(sizeof(struct ButtonsArg) + nbImages*sizeof(char*));
for(int i = 0; i < nbImages; i++) {
arg->img[i] = malloc(strlen(images[i])+1);
strcpy(arg->img[i], images[i]);
}
arg->image = image;
g_signal_connect(precedent, "clicked", G_CALLBACK(event_precedent), &arg);
Here's the function where the problems occur:
static void event_previous(GtkWidget *widget, gpointer data) {
g_print ("previous\n");
struct ButtonsArg *arg = data;
//Print weird charac
for(int i = 0; i < nbImages; i++) {
printf("%s\n", arg->img[i]);
}
GtkWidget *image = arg->image;
if(currentImage == 0) {
currentImage = nbImages - 1;
gtk_image_set_from_file (GTK_IMAGE (arg->image), arg->img[1]);
} else {
currentImage--;
gtk_image_set_from_file (GTK_IMAGE (arg->image), arg->img[2]);
}
}
If you have any advice, help or link that could help, thanks for sharing it with me.

Can you show the part of code where you try to change GtkImage variable? Seems like program was trying to set the null-value to GtkImage-type variable. In this cause any expression with this variable (like image->value) can raise segementation fault.
UPD: Ok. I see it. You should be check the arg-structure. I think, some attribute of this structure can have null-value.

Related

GLib: cannot initialize GValue [...] the value has already been initialized as '(null)'

I spot very strange behavior using a GValue:
This code runs fine:
#include <gtk/gtk.h>
int
main(int argc, char *argv[])
{
gtk_init(&argc, &argv);
{
GValue value;
g_value_init (&value, G_TYPE_STRING);
g_value_set_string (&value, "hallo");
gchar * strVal = g_strdup_value_contents (&value);
g_print ("gvalue: %s\n", strVal);
free (strVal);
g_value_unset (&value);
}
return 0;
}
However, the following code spawns the warning cannot initialize GValue with type 'gchararray', the value has already been initialized as '(null)' in the marked line.
Note, that the only thing, that's changed, is the new block with another GValue inside.
#include <gtk/gtk.h>
int
main(int argc, char *argv[])
{
gtk_init(&argc, &argv);
{
GValue value;
g_value_init (&value, G_TYPE_STRING);
g_value_set_string (&value, "hallo"); // warning spawns here
gchar * strVal = g_strdup_value_contents (&value);
g_print ("gvalue: %s\n", strVal);
free (strVal);
g_value_unset (&value);
}
{
GValue value2;
g_value_init (&value2, G_TYPE_INT);
g_value_set_int (&value2, 15);
gchar * strVal = g_strdup_value_contents (&value2);
g_print ("gvalue: %s\n", strVal);
free (strVal);
g_value_unset (&value2);
}
return 0;
}
Can someone tell me what is going on here?
You improperly initialized GValue.
GValue value = G_VALUE_INIT;
Not initialized variables at block scope have some garbage value, which may happen to be invalid and trigger an assertion (or may happen to be valid and nothing happens).

Why does my Thrift (c_glib) client fail with an "invalid pointer" error?

I'm creating a simple thrift server/client program in C (g_lib).
This is how my thrift IDL file looks like:
namespace cpp tutorial
service Calculator {
void ping(),
binary getdata()
}
And the implementation for getdata on the thrift server looks like this:
static gboolean
tutorial_calculator_handler_getdata (CalculatorIf *iface,
GByteArray *_return,
GError **error)
{
THRIFT_UNUSED_VAR (iface);
THRIFT_UNUSED_VAR (error);
puts ("getdata()");
GByteArray *gbarray;
gint i;
gbarray = g_byte_array_new ();
for (i = 0; i < 100; i++)
g_byte_array_append (gbarray, (guint8*) &i, 1);
*_return = *gbarray;
return TRUE;
}
Now, on the client side, I'm calling the getdata as follows:
....
....
GByteArray *data;
....
....
if (!error && calculator_if_getdata (client, &data, &error)) {
puts ("getdata()");
}
Unfortunately, the client crashes with the following message in the calculator_if_getdata call:
*** Error in `./client': munmap_chunk(): invalid pointer: 0xb741742d ***
Aborted (core dumped)
Is this the correct way to send an array of integers from the server to client in thrift? What am i doing wrong here?
I see three issues with what you're doing here:
If a service method returns a complex type, the _return parameter passed to its handler function will point to a pre-allocated structure that should not be destroyed or re-created. Your code should be appending values to the GByteArray to which _return already points, not creating a GByteArray of its own.
Although you shouldn't be trying to modify the value of _return anyway, the way your code does this is incorrect and ends up clobbering the data structure to which _return points. This most likely explains the error message you're seeing.
Your code declares i a thirty-two bit integer but appends to the byte array only i's first byte. This will not have the effect you intend on every machine architecture.
I figured it out after spending some time on it, here's the working handler and the client side implementation code:
gboolean
tutorial_calculator_handler_getdata (CalculatorIf *iface,
GByteArray ** _return,
GError **error)
{
THRIFT_UNUSED_VAR (iface);
THRIFT_UNUSED_VAR (error);
GByteArray *thing = g_byte_array_new();
*_return = g_byte_array_new();
guint8 i;
for (i = 0; i < 10; i++){
g_byte_array_append (thing, (guint8*) &i, sizeof(guint8));
}
g_byte_array_append(*_return, (guint8*) thing->data, thing->len);
return TRUE;
}
And the client side:
GByteArray *data = g_byte_array_new();
if (!error && calculator_if_getdata (client, &data, &error)) {
puts ("getdata()");
printf ("Data : %d\n", data);
guint8 i;
guint8 size = sizeof(guint8);
for(i=0;i<10;i++)
printf ("Data : %d\n", data->data[size*i]);
}

How to load GdkPixbuf from file in a callback function?

I'm using gtk+ 3.14 and I want to load a picture that the user chooses.
The code here correctly displays the picture but doest not seem to update
the GdkPixbuf *pixbuf. In fact, GdkPixbuf is not NULL inside the function but it
is NULL outside it. What can I do to correctly load and use pixbuf in other functions ?
Here is the callback structure :
struct callback_struct
{
GdkPixbuf *pix;
GtkWidget *img;
int height;
int width;
float scale;
};
Here is my code :
void callback_load(gpointer data)
{
struct callback_struct *passed = data;
GdkPixbuf *pixbuf = passed->pix;
GtkWidget *image = passed->img;
int h_scr = passed ->height;
int w_scr = passed->width;
float scale = passed->scale;
GtkWidget *dial_box = gtk_file_chooser_dialog_new("Choose the image to load"
,GTK_WINDOW(gtk_widget_get_toplevel(image)),
GTK_FILE_CHOOSER_ACTION_OPEN,
"Cancel",GTK_RESPONSE_CANCEL,"Open",GTK_RESPONSE_ACCEPT,NULL);
switch (gtk_dialog_run (GTK_DIALOG (dial_box)))
{
case GTK_RESPONSE_ACCEPT:
{
gchar *filename =gtk_file_chooser_get_filename
(GTK_FILE_CHOOSER (dial_box));
pixbuf = gdk_pixbuf_new_from_file(filename,NULL);
printf("%d\n",(pixbuf == 0));
GdkPixbuf *scaled_buffer = gdk_pixbuf_scale_simple
(pixbuf,h_scr*scale,w_scr*scale,GDK_INTERP_BILINEAR);
gtk_image_set_from_pixbuf(GTK_IMAGE(image),scaled_buffer);
printf("%d\n",(pixbuf == 0));
gtk_widget_destroy(dial_box);
break;
}
case GTK_RESPONSE_CANCEL:
{
gtk_widget_destroy(dial_box);
break;
}
}
}
You only modify the local pointer pixbuf: in fact passed->pix is NULL throughout the code.
You should either not use a local pointer at all (and just refer to passed->pix) , or alternatively set the structs pointer equal to the local pointer at some point after initializing it.

Placing images in a fixed layout GTK2

I have an application that is attempting to do the following:
Create a GTK2 top level main window
Add a fixed frame into the main window for absolute positioning of widgets
Create a matrix of GtkImages that will be used to display animated GIFS and static JPEGS
On start-up the static JPEGS picked randomly from a list will fill the matrix
When an event happens the matrix will be filled with animated GIFS
When the animation is over possibly different JPEGS will again be displayed in the matrix
Run time errors are happening only when two or more of the randomly selected JPEGS are placed in a row of the matrix.
Here is an example of such a run time error:
(wrong:3909): Gtk-WARNING **: Can't set a parent on widget which has a parent
If each image of the row are unique no run time errors occur.
Code snippets and run time output are as follows:
/*
* Compile me with:
* gcc -Wall -o wrong wrong.c $(pkg-config --cflags --libs gtk+-2.0 gmodule-2.0)
*/
/* header includes */
/**** prototypes ****/
/********************/
typedef struct
{
unsigned int pixel_width, pixel_height;
gchar fileName[20];
GtkWidget *image;
}symbol_t;
symbol_t symbols[] =
{
{ 118, 107, "images/LO.jpg", NULL },
{ 118, 107, "images/L1.jpg", NULL },
{ 118, 107, "images/L2.jpg", NULL },
{ 118, 107, "images/L3.jpg", NULL },
{ 118, 107, "images/H1.jpg", NULL },
{ 118, 107, "images/H2.jpg", NULL },
{ 118, 107, "images/H3.jpg", NULL },
{ 118, 107, "images/H4.jpg", NULL },
{ 118, 107, "images/H5.jpg", NULL }
};
GtkWidget *frame; /* for absolute positioning of widgets */
GtkWidget *window;
int Init( void )
{
/* initialize random number generator */
}
static void destroy (GtkWidget *window, gpointer data)
{
gtk_main_quit ();
}
GtkWidget *SetupWindow(gchar *data, const gchar *filename)
{
/* setup top-level window setting the background to the image contained
in *filename and return window widget
*/
return(window);
}
int main (int argc, char *argv[])
{
unsigned int y, i, pos_x, pos_y;
gtk_init (&argc, &argv);
Init(); // init random number generator
window = SetupWindow("Broken", "images/background.jpg");
g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (destroy), NULL);
frame = gtk_fixed_new();
gtk_container_add(GTK_CONTAINER(window), frame);
/* setup symbol jpgs */
for( i = 0; i < 9; i++ )
{
/* load each symbol image into memory */
symbols[i].image = gtk_image_new_from_file( symbols[i].fileName );
}
/* display some symbols */
pos_y = 150;
pos_x = 187;
for( y = 0; y < 5 ; y++ ) /* first row - 5 symbols */
{
i = (unsigned int)(random()%9);
printf("Symbol[%d] [%s]\n", i, symbols[i].fileName);
gtk_fixed_put(GTK_FIXED(frame), symbols[i].image, pos_x, pos_y);
pos_x += symbols[i].pixel_width;
}
gtk_widget_show_all(window);
gtk_main ();
return 0;
}
Run time errors when two or more matching symbols ( images ) are placed on the row:
[chim] ~/source/matrix > ./wrong
Symbol[1] [images/L1.jpg]
Symbol[7] [images/H4.jpg]
Symbol[0] [images/LO.jpg]
Symbol[7] [images/H4.jpg]
(wrong:3909): Gtk-WARNING **: Can't set a parent on widget which has a parent
Symbol[5] [images/H2.jpg]
(wrong:3909): Gtk-CRITICAL **: gtk_widget_destroy: assertion `GTK_IS_WIDGET (widget)' failed
(wrong:3909): Gtk-CRITICAL **: gtk_widget_destroy: assertion `GTK_IS_WIDGET (widget)' failed
When this occurs some of the images in the row are empty ( white ).
Output when no matching symbols ( images ) are placed on the row:
[chim] ~/source/matrix > ./wrong
Symbol[1] [images/L1.jpg]
Symbol[6] [images/H3.jpg]
Symbol[3] [images/L3.jpg]
Symbol[0] [images/LO.jpg]
Symbol[4] [images/H1.jpg]
And in this case all images are displayed properly.
Any suggestions about how to fix and what I might be doing wrong?
Once you place the image into another widget, it becomes owned and managed by that (parent) widget -- you can't add it to more than one widget.
The simple way to get this to work is to load the image with gtk_image_new_from_file() each time you want to add it to the window. If you don't want to do that, maybe you can use something like gtk_image_new_from_image() to copy the image prior to adding it to the widget.

Change window title - `GTK_IS_WINDOW (window)' failed

I want to change titlie of main window of my C/gtk+ application. I have code:
void update_title(const char *filename, MainWin* mw )
{
GtkButton* btn = gtk_button_new();
static int wid, hei;
static char fname[50];
char buf[100];
if(filename != NULL)
{
strncpy(fname, filename, 49);
wid = gdk_pixbuf_get_width( gtk_image_view_get_pixbuf (GTK_IMAGE_VIEW(aview)) );
hei = gdk_pixbuf_get_height( gtk_image_view_get_pixbuf ( GTK_IMAGE_VIEW(aview)) );
fname[49] = '\0';
}
snprintf(buf, 100, "%s (%dx%d) %d%%", fname, wid, hei, (int)(mw->scale * 100));
gtk_window_set_title(mw, buf);
}
When i try to call this function i see error: Gtk-CRITICAL **: gtk_window_set_title: assertion `GTK_IS_WINDOW (window)' failed
What's wrong?
Thank you.
mw is of MainWin type, gtk_window_set-title() expect a GtkWindow type.
You are repeatidly asking the same question and you'll repeatedly receive the same answer. These are your options:
Learn how to properly subclass a GObject
Write a proper question, such as I'm trying to subclass a GtkWindow with this code but...
Goto 1.

Resources