Search code examples
cglibgnomedynamic-arrays

glib how address to index g_ptr_array


I have 3 structures and I use GNOME glib library to have dynamic array.

typedef struct Neuron
{
    //number of inputs into neuron
    int NumInputs; 

    //growing array of weights for each input
    GArray* ArrWeight;

}neuron;

typedef struct NeuronLayer
{
    //number of neurons in layer
    int NumNeurons;
    //growing array of neurons 
    GPtrArray* ArrNeurons;
}layer;

typedef struct Net
{
    int numInputs;
    int numOutputs;
    int numHiddenLayers;
    int NeuronsPerHiddenLayer;
    //each layer of neurons 
    GPtrArray* ArrLayers;
}net;

I want write cycle like that

for (k = 0; k < Net->ArrLayers->pdata[i].ArrNeuron->pdata[j].NumInputs; k++)

But I dont know how address to array. Compiler (clang say) :

member reference base type 'gpointer' (aka 'void *') is not a structure or union.

structure of Gptrarray:

 struct GPtrArray 
 {   
    gpointer *pdata;   
    guint    len; 
 };

I think i should write something like that

Net->ArrLayers->pdata[i*sizeof(layer)].ArrNeurons->pdata[j*sizeof(neuron)].NumInputs

Solution

  • gpointer is a generic pointer. You are using it to store a pointer of a specific type. So to access its elements you must use a type cast.

    I will first try to break your statement down. It currently looks like this:

    Net->ArrLayers->pdata[i].ArrNeuron->pdata[j].NumInputs
    

    I assume Net is a variable of type net *.

    Net->ArrLayers is of type GPtrArray *.

    Net->ArrLayers->pdata is of type gpointer *, i.e. void **, a pointer to a pointer.

    Net->ArrLayers->pdata[i] is thus of type gpointer, i.e. void *, a pointer.

    Now you want to access its element. Judging from your context, you want to interpret this pointer as a pointer to layer. However, the compiler doesn't know that. You need to tell the compiler.

    So you should add a cast, (layer *)Net->ArrLayers->pdata[i].

    Now since this is of type layer * and not layer, you still need -> instead of . to access its element, so it should now become:

    ((layer *)Net->ArrLayers->pdata[i])->ArrNeuron
    

    Now you need to access pdata again. This is the same as the above, so I'll skip the explanation and show you the correct method:

    ((neuron *)((layer *)Net->ArrLayers->pdata[i])->ArrNeuron->pdata[j])->NumInputs
    

    As you can see this is very messy. It would be better to split this into several statements to enhance readability, and by doing so you may even skip the casts:

    int current_num_inputs(net * Net, size_t i, size_t j) {
        layer *current_layer = Net->ArrLayers->pdata[i];
        neuron *current_neuron = current_layer->ArrNeuron->pdata[j];
        return current_neuron->NumInputs;
    }
    

    Then in your for loop:

    for(k = 0; k < current_num_inputs(Net, i, j); k++) { // ...