#MessageStorageInsideStruct 11/25/2022 # #https://www.perlmonks.org/?node_id=11148268 # # # use strict; use warnings; use Inline C => Config => BUILD_NOISY => 1, CLEAN_AFTER_BUILD => 1, USING => 'ParseRegExp', ; use Inline "C"; struct_size(); my @in = ("hello foo", "hello bar","hello world", "goodbye", '1', '2', '3'); foo(\@in); print "back inside Perl program!!!!\n"; print "printout is not in time order you expected!\n\n"; =EXAMPLE RUN back inside Perl program!!!! printout is not in time order you expected! Size of _Edje_Message_String_Set structure: 8 bytes Address of the Message Struct: 000000000308FAB8 Address of the Pointer Array: 000000000308FAC0 setting element 0 string: hello foo's pointer is at Address 000000000308FAC0 setting element 1 string: hello bar's pointer is at Address 000000000308FAC8 setting element 2 string: hello world's pointer is at Address 000000000308FAD0 setting element 3 string: goodbye's pointer is at Address 000000000308FAD8 setting element 4 string: 1's pointer is at Address 000000000308FAE0 setting element 5 string: 2's pointer is at Address 000000000308FAE8 setting element 6 string: 3's pointer is at Address 000000000308FAF0 Dumping an EdjeMessageStringSet Count = 7 1) hello foo 2) hello bar 3) hello world 4) goodbye 5) 1 6) 2 7) 3 Destroying an EdjeMessageStringSet =cut __END__ __C__ /*********** Start of C Code ********/ struct _Edje_Message_String_Set { int count; //On 64 bit machine, this is 8 bytes char *str[]; //str has no "size" and is not counted in sizeof(_Edje_Message_String_Set) }; typedef struct _Edje_Message_String_Set EdjeMessageStringSet; void struct_size(void) { printf("Size of _Edje_Message_String_Set structure: %d bytes\n", sizeof(EdjeMessageStringSet) ); } /************/ EdjeMessageStringSet * _new(AV* val_arr) { int count = av_len(val_arr) + 1; // newer av_count() not avail this version // sizeof(Edje_Message_String_Set) only has the integer,count of 8 bytes // space for the array of pointers must be allocated by safemalloc // remember to add one more slot for a NULL pointer EdjeMessageStringSet* message = (EdjeMessageStringSet*) safemalloc ( sizeof(EdjeMessageStringSet) + (count+1)*sizeof(char*) ); printf ("Address of the Message Struct: %p\n",message); if(message == NULL) croak("Failed to allocate memory for message in _new function"); message->count = count; char** p = &(message->str[0]); printf ("Address of the Pointer Array: %p\n", p); int i; for(i= 0; i < message->count; i++) { printf ("setting element %d\n",i); SV** elem = av_fetch(val_arr, i, 0); if (elem==NULL) croak ("bad SV elem value in _new function"); char* string = SvPVutf8_nolen(*elem); printf ("string: %s's pointer is at Address %p\n",string,p); *p++ = savepv(string); } *p = NULL; //Can use either count or NULL pointer as a loop variable return message; } /******************/ void _iterate (EdjeMessageStringSet* m) { printf ("Dumping an EdjeMessageStringSet\n"); printf ("Count = %d\n",m->count); int i = 1; char** p = &(m->str[0]); while (*p) {printf ("%d) %s\n",i++,*p++);} } void DESTROY(EdjeMessageStringSet* m) { printf ("Destroying an EdjeMessageStringSet\n"); char** p = &(m->str[0]); while(*p){Safefree(*p++);} //zap eaxh cloned string Safefree(m); //zap main structure } /************/ void foo(AV * arref) { EdjeMessageStringSet* m = _new(arref); _iterate(m); DESTROY(m); }