views:

205

answers:

3

Hi there, I'm trying to build a GHashTable of instances of a struct containing ints, a time_t and a few char*'s.

My question is, how do you insert an instance of a struct into a GHashTable? there are plenty of examples of how to insert a string or an int (using g_str_hash and g_int_hash respectively), but I'm guessing thatI want to use the g_direct_hash, and I can't seem to find any examples of that.

Ideally, my code would look like this:

GHashtable table;
table = g_hash_table_new(g_direct_hash, g_direct_equal);
struct mystruct;
mystruct.a = 1;
mystruct.b = "hello";
mystruct.c = 5;
mystruct.d = "test";

g_hash_table_insert(table,mystruct.a,mystruct);

Clearly, this is incorrect as it does not compile. Can anyone provide an example that does do what I want? Thanks, Rik

+1  A: 

You have to allocate the structures on the heap so you can store a pointer in the hash table:

struct SomeType * p = malloc(sizeof(struct SomeType));
p->a = 1;
//etc..
g_hash_table_insert(table,p->a,p);

You'll also need to use g_hash_table_new_full() so you can properly free the pointers when the table is destroyed.

Hans Passant
+2  A: 

You can't insert an automatic variable; you have to allocate memory for the data to store in a dynamic way, i.e. using g_malloc() or equivalent.

Then you need to figure out a way to compute a hash value from your data, to help the table be efficient. Using g_direct_hash() is not very good here; it will use the pointer to your data as the hash value.

It seems as if you want to use the member a of your structure as the key; what type is this field? If it's integer, you can use g_int_hash().

I think this is more along the lines of what your actual code should look like:

GHashtable *table;
struct mystruct *my;

table = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, g_free);
my = g_malloc(sizeof *my);
my->a = 1;
my->b = "hello";
my->c = 5;
my->d = "test";

g_hash_table_insert(table, GINT_TO_POINTER(my->a), my);

Note that this assumes that the b and d members are simply character pointers, since no storage is dynamically allocated for the strings.

unwind
`table = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, g_free);`
ntd
@ntd: Thanks, and fixed!
unwind
+1  A: 

Thanks. The above examples helped. After reading these and going through code samples on the net, I could make it work. Following is a sample working code I wrote:


#include <stdio.h>
#include <glib.h>
#include <stdlib.h>

struct struct_process {
    int pid;
    char* file_to_process;
};

typedef struct struct_process Process;

int main() {
    GHashTable* hash_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);

    Process* p1 = (Process*)(malloc(sizeof(Process)));
    p1->pid = 1234;
    p1->file_to_process= "/var/tmp/p1";

    g_hash_table_insert(hash_table, GINT_TO_POINTER(p1->pid), GINT_TO_POINTER(p1));

    # replace 1234 by some other key to see that it returns NULL on nonexistent keys
    Process* p3 = (Process*)(g_hash_table_lookup(hash_table, GINT_TO_POINTER(1234))); 

    if (p3 == NULL) {
       printf("could not find\n");
    } else {
       printf("found and i have to process %s\n", p3->file_to_process);
    }
    g_hash_table_destroy(hash_table);
}
`
Saurabh Hirani