Hvordan dynamisk lage og lese structs i C?

stemmer
6

Hvordan kan jeg gjøre noe sånt (bare et eksempel):

any_struct *my_struct = create_struct();
add_struct_member(my_struct, a, int_member);
add_struct_member(my_struct, b, float_member);

Slik at jeg kunne laste og bruke en struct eksempel utenfra (på adressen addressOfMyStruct) med den gitte struktur her?

any_struct_instance *instance = instance(my_struct, addressOfMyStruct);
int a = instance_get_member(instance, a);
float b = instance_get_member(instance, b);

Jeg ønsker også å være i stand til å skape struct tilfeller dynamisk på denne måten.

Jeg håper det er klart hva jeg ønsker å gjøre. Jeg vet at C / Invoke er i stand til å gjøre det, men er det et eget bibliotek for å gjøre det?

Publisert på 22/04/2009 klokken 15:05
kilden bruker
På andre språk...                            


3 svar

stemmer
6

Faktisk viser koden for å gjøre dette arbeidet i C er en smule for involvert for en SO innlegg. Men å forklare grunnleggende konseptet er gjennomførbart.

Det du egentlig lage her er et malbasert eiendom bag system. Det eneste du trenger mye å holde dette kommer er noen assiociative struktur som en hash table. Jeg vil si gå med std :: kart, men du nevnte dette var en eneste C løsning. For å få til diskusjonen jeg bare kommer til å anta at du har noen form for hashtabellen tilgjengelig.

Den "create_struct" call må returnere en struktur som inneholder en peker til en hashtabellen som gjør const char*til i det vesentlige en size_t. Dette kartet definerer hva du trenger for å lage en ny forekomst av struct.

Den "insance" metoden vil i det vesentlige skape en ny hashtabellen med likt antall medlemmer som templat hashtabellen. Lar kaste lat evualation ut av vinduet for en andre og antar du opprette alle medlemmer opp foran. Metoden må sløyfe over boremalen hashtabellen tilsette et medlem for hver oppføring og malloc'ing et minne del av den angitte størrelse.

Gjennomføringen av instance_get_member vil bare gjøre et oppslag i kartet ved navn. Signaturen selv og bruksmønster må endre skjønt. C støtter ikke maler og må velge en felles returtype som kan representere alle data. I dette tilfellet må du velge void*siden det er hvordan minnet må lagres.

void* instance_get_member(any_struct_instance* inst, const char* name);

Du kan gjøre dette litt bedre ved å legge en envil makro å simulere maler

#define instance_get_member2(inst, name, type) \
  *((type*)instance_get_member((inst),(name)))
...
int i = instance_get_member2(pInst,"a", int);
Svarte 22/04/2009 kl. 15:17
kilden bruker

stemmer
1

Du har gått så langt som definerer problemet at alt som er igjen er litt av (litt vanskelig i enkelte deler) implementering. Du trenger bare å holde styr på informasjon:

typedef struct {
    fieldType type;
    char      name[NAMEMAX];
    /* anything else */
} meta_struct_field;
typedef struct {
    unsigned          num_fields;
    meta_struct_field *fields;
    /* anything else */
} meta_struct;

Deretter create_struct()tildeler minne for meta_structog initialisert den til 0, og add_struct_member()gjør en alloc()/ realloc()my_struct.fieldsog intervaller my_struct.num_fields. Resten følger i samme retning.

Du vil også ha en unioni meta_struct_fieldå holde faktiske verdier i tilfeller.

Svarte 22/04/2009 kl. 15:22
kilden bruker

stemmer
0

Jeg gjorde noe av dette for lenge siden.

Slik jeg gjorde det var å generere koden inneholder struct definisjon, pluss alle rutiner for å bruke den og deretter å bygge og koble den til en DLL "on the fly", legger da det DLL dynamisk.

Svarte 22/04/2009 kl. 15:28
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more