Struct di callback e direttive di inclusione

di il
14 risposte

Struct di callback e direttive di inclusione

Buongiorno a tutti. Partite dal presupposto che sono in fase di apprendimento, per cui il problema che vi pongo sarà per alcuni alquanto stupido; negli ultimi giorni svolgendo alcuni esercizi sulle callback, sono inciampata in errori di compilazione che credo siano dovuti ad errori che faccio nello scrivere le direttive di inclusione al preprocessore, quando si tratta di progetti composti da più moduli. Sbagliare con le direttive di inclusione è sbagliare l'abc proprio, ecco perchè prima di scrivervi ho fatto varie ricerche nei manuali, ma mi è risultato comunque complicato capire gli errori.
Il codice che posto di seguito non ha alcun senso in se per se, ho scritto una porzione di codice esemplificativa (con i medesimi errori di compilazione), per chiedere il vostro aiuto.

main.c
#include <stdio.h>
#include <stdlib.h>

#include "mytype.h"
#include "dataINT.h"
#include "dataFLOAT.h"
#include "libreria.h"

int main(){
    int scelta;
    TYPE func;
    DATO d;
    printf("Scegli tipo di dato\n1)Intero\n2)Float\n\n");
    scanf("%d",&scelta);
    switch(scelta){
        case 1:
            func=set_INT();
            break;
        case 2:
            func=set_FLOAT();
            break;
        }

    d=lib_init(func);
    d=lib_insert(d);
    lib_print(d);

    system("PAUSE");
    return 0;
}
mytype.h
#ifndef MYTYPE_H_INCLUDED
#define MYTYPE_H_INCLUDED

typedef struct funz_type{
    void *(*input) (void);
    void *(*random) (void);
    void (*print) (void*);

    //altre callback
    }TYPE;

#endif // MYTYPE_H_INCLUDED
libreria.h
#ifndef LIBRERIA_H_INCLUDED
#define LIBRERIA_H_INCLUDED

struct t_dato{
    void * dato;
    TYPE func;
    }t_dato;
typedef struct t_dato * DATO;

DATO lib_init(TYPE f);
DATO lib_insert();
void lib_print(DATO d);

#endif // LIBRERIA_H_INCLUDED
libreria.c
#include <stdio.h>
#include "mytype.h"
#include "libreria.h"

DATO lib_init(TYPE f){
    DATO d=(t_dato*)malloc(sizeof(struct t_dato);
    d->dato=NULL;
    d->func=f;
    return d;
    }

DATO lib_insert(DATO d){
    int scelta;
    printf("*** INSERT \n1)Random\n2)Inserisci Manualmente\n\n");
    scanf("$d",&scelta);
    if(scelta==1)
        d->func.random();
    else
        d->func.input();

    return d;
}

void lib_print(DATO d){
    d->func.print(d->dato);
    return;
    }
dataINT.h
#ifndef DATAINT_H_INCLUDED
#define DATAINT_H_INCLUDED

void * inputINT (void);
void * randomINT (void);
void printINT (void * a);

TYPE set_INT();

#endif // DATAINT_H_INCLUDED
dataINT.c
#include <stdio.h>
#include <stdlib.h>
#include "mytype.h"
#include "dataINT.h"

void * inputINT (void){
    int *in=malloc(sizeof(int));
    printf("Inserisci INTERO: ");
    scanf("%d", in);
    return in;
}

void * randomINT (void){
    int *in=malloc(sizeof(int));
    *in= (rand()%100) ;
    return in;
}

void printINT (void * a){
    int in= *(int*) a;
    printf("%d\n", in);
}


TYPE set_INT(){
    TYPE f;
    f.input=&inputINT;
    f.random=&randomINT;
    f.print=&printINT;
    }
dataFLOAT.h
#ifndef DATAFLOAT_H_INCLUDED
#define DATAFLOAT_H_INCLUDED

void * inputFLOAT (void);
void * randomFLOAT (void);
void printFLOAT (void * a);

TYPE set_FLOAT();

#endif // DATAFLOAT_H_INCLUDED
dataFLOAT.c
#include <stdio.h>
#include <stdlib.h>
#include "mytype.h"
#include "dataFLOAT.h"

void * inputFLOAT (void){
    float *in=malloc(sizeof(float));
    printf("Inserisci NUMERO CON VIRGOLA: ");
    scanf(" %f", in);
    return in;
}

void * randomFLOAT (void){
    float *in=malloc(sizeof(float));
    int k= rand()%100;
    *in=rand()%100;
    *in=((*in)/k)+k;
    return in;
}

void printFLOAT (void * a){
    float in= *(float*) a;
    printf("%.2f\n", in);
}


TYPE set_FLOAT(){
    TYPE f;
    f.input=&inputFLOAT;
    f.random=&randomFLOAT;
    f.print=&printFLOAT;
    }
Quello che mi serviva è avere una struttura dati che contenga le callback, la cui definizione sia visibile a diverse librerie.. in questo caso specifico, da "libreria","dataINT", etc.... Ecco perchè ho pensato di inserire la struct in un file a sè, da includere dove mi serve... Quello che ho ottenuto è un macello!
Con questo ordine degli #include nel main ottengo errori di "undefinited reference to..." a tutte le funzioni, ma cambiando l'ordine comunque incorro nel problema che "libreria.h" non vede il tipo "TYPE"..... Per cui non riesco ad uscirne.. help!
Grazie anticipatamente!

14 Risposte

  • Re: Struct di callback e direttive di inclusione

    Beh, diciamo che è un bel casino, faresti prima a fare un pacchetto e linkare quello postando anche il comando o il makefile che utilizzi per la compuilazione.

    In ogni caso, la prima cosa che noto è che sia set_INT che set_FLOAt non ritornano nulla....


    Una nota importante: non nascondere MAI i puntatori con le typedef , rende il codice illeggibile ed è una delle prime cause di errore. Non costa molto usare * davanti a tutto quello che vuoi sia un puntatore...
  • Re: Struct di callback e direttive di inclusione

    LPs ha scritto:


    Beh, diciamo che è un bel casino, faresti prima a fare un pacchetto e linkare quello postando anche il comando o il makefile che utilizzi per la compuilazione.
    Sarebbe? Non ho molta esperienza, anzi zero
    In ogni caso, la prima cosa che noto è che sia set_INT che set_FLOAt non ritornano nulla....
    hai ragione ho sbagliato a copiare la funzione, ovviamente ci va un return f in entrambe
    Una nota importante: non nascondere MAI i puntatori con le typedef , rende il codice illeggibile ed è una delle prime cause di errore. Non costa molto usare * davanti a tutto quello che vuoi sia un puntatore...
    Ti ringrazio per questo consiglio, lo applicherò.
  • Re: Struct di callback e direttive di inclusione

    violet_prog ha scritto:


    LPs ha scritto:


    Beh, diciamo che è un bel casino, faresti prima a fare un pacchetto e linkare quello postando anche il comando o il makefile che utilizzi per la compuilazione.
    Sarebbe? Non ho molta esperienza, anzi zero
    .
    Fai un pacchetto zip con i sorgenti e aggiungilo al post.
    Inoltre come lo compili? Da riga di comando o altro? Compilatore utilizzato?
  • Re: Struct di callback e direttive di inclusione

    Ahh.. aggiungerla qui intendi!
    Comunque uso codebocks, è rilevante ai fini del mio problema?!
    A me interessa che il codice sia portabile poi, perchè il prof certo non lo eseguirà su codeblocks
  • Re: Struct di callback e direttive di inclusione

    Ecco fatto.
    L'ho leggermente modificato.. cioè ho aggiunto mytype.c dove ho implementato le funzioni di set delle callback, perchè ho pensato di rendere i file dei dati indipendenti dalla struct delle callback
    Così come l'ho allegato ho due errori di compilazione in libreria.h 'TYPE is not declared in this scope'
    Allegati:
    15378_2fa390f39c6f2e56f60c43dd2413fb0f.zip
    15378_2fa390f39c6f2e56f60c43dd2413fb0f.zip
  • Re: Struct di callback e direttive di inclusione

    Ok. Prima cosa non hai nessun errore di compilazione.....

    Seconda cosa il vero errore che vedo è che la funzione lib_insert chiama correttamente le funzioni della struttura, ma non assegna il risultato a nulla e quando viene chiamata la funzione di stampa il membro dato ha un puntatore a NULL:
    
    DATO lib_insert(DATO d)
    {
    	int scelta;
    	printf("*** INSERT \n1)Random\n2)Inserisci Manualmente\n\n");
    	scanf("%d", &scelta);
    
    	if (scelta == 1)
    		d->dato = d->func.random();
    	else
    		d->dato = d->func.input();
    
    	return d;
    }
    
    Inoltre tieni in considerazione che la malloc può fallire, quindi ogni volta che le usi il valore che ti ritorna deve essere != NULL
  • Re: Struct di callback e direttive di inclusione

    LPs ha scritto:


    Ok. Prima cosa non hai nessun errore di compilazione.....

    Ma com'è possibile?
    Ecco i due errori che mi escono :
    C:\Users\...\libreria.h|6|error: 'TYPE' does not name a type|
    C:\Users\...\libreria.h|10|error: 'TYPE' was not declared in this scope|
    Ma... da cosa dipende? Allora l'errore non è nel codice? Come l'hai compilato?
    Seconda cosa il vero errore che vedo è che la funzione lib_insert chiama correttamente le funzioni della struttura, ma non assegna il risultato a nulla e quando viene chiamata la funzione di stampa il membro dato ha un puntatore a NULL:
    
    DATO lib_insert(DATO d)
    {
    	int scelta;
    	printf("*** INSERT \n1)Random\n2)Inserisci Manualmente\n\n");
    	scanf("%d", &scelta);
    
    	if (scelta == 1)
    		d->dato = d->func.random();
    	else
    		d->dato = d->func.input();
    
    	return d;
    }
    
    Giusto. Non compilando non mi sono neanche resa conto di questo errore di distrazione.
    Inoltre tieni in considerazione che la malloc può fallire, quindi ogni volta che le usi il valore che ti ritorna deve essere != NULL
    Intendi che devo fare sempre un if sul dato allocato?
    if(datoallocato == NULL) 
    	//allocazione fallita
    	
  • Re: Struct di callback e direttive di inclusione

    Il file myType.h è incluso prima di Libreria.h nel main, quindi il compilatore dovrebbe vedere il tipo TYPE.

    Probabilmente dipende da come stai compilando: riesci a risalire al comando di compilazione? Non conosco codeblocks..
  • Re: Struct di callback e direttive di inclusione

    LPs ha scritto:


    Il file myType.h è incluso prima di Libreria.h nel main, quindi il compilatore dovrebbe vedere il tipo TYPE.

    Probabilmente dipende da come stai compilando: riesci a risalire al comando di compilazione? Non conosco codeblocks..
    Ma infatti è questo il motivo per cui non riuscivo a capire l'errore!
    Ora faccio una ricerca per risalire al comando di compilazione, invece con cosa tu l'hai compilato?
  • Re: Struct di callback e direttive di inclusione

    Io, su linux, da riga di comando faccio veloce
    
    gcc -Wall -Wextra -pedantic -lpthread dataFLOAT.c dataINT.c libreria.c mytype.c main.c -o pippo -std=c11  -g -lm
    
  • Re: Struct di callback e direttive di inclusione

    LPs ha scritto:


    Io, su linux, da riga di comando faccio veloce
    
    gcc -Wall -Wextra -pedantic -lpthread dataFLOAT.c dataINT.c libreria.c mytype.c main.c -o pippo -std=c11  -g -lm
    
    Sono riuscita a risalire alla riga di comando.. e bhe... usava g++! Quindi ora funziona e tutto ok.... però compilandolo mi sono resa conto che non emulava il problema che invece avevo.. e perciò ci ho aggiunto un'altra (inutile) libreria, ed ecco qua la questione che mi chiedevo sin dal principio. La riga dove si ha l'errore di compilazione l'ho commentata..
    Ps: Devo ancora aggiungere il controllo per la malloc
    Allegati:
    15378_95f1cbbf6282a66de470563ec6fdee92.zip
    15378_95f1cbbf6282a66de470563ec6fdee92.zip
  • Re: Struct di callback e direttive di inclusione

    Ua! Credo di aver risolto... dovevo includere prima libreria, e poi libreriabis.. credo. Faccio i dovuti controlli....
  • Re: Struct di callback e direttive di inclusione

    violet_prog ha scritto:


    Ua! Credo di aver risolto... dovevo includere prima libreria, e poi libreriabis.. credo. Faccio i dovuti controlli....
    Bene!
  • Re: Struct di callback e direttive di inclusione

    Confermo! Sono riuscita! Che errore sciocco!! In realtà nel mio esercizio più grande in libreriabis.c mancavo anche l'inclusione di mytype.h prima di libreria.h Grazie mille!
Devi accedere o registrarti per scrivere nel forum
14 risposte