struct _Edje_Message_String_Set
{
int count;
char * str[];
};
Is it possible to handle that ?
Yes, it sure is!
I actually decided that this is the best way to implement the idea of the array of pointer within the struct itself. My reasoning is that the [] gives a big clue that there is no storage in the struct at all for the array of pointers to strings.
In my implementation below, I allocated one more slot for a NULL pointer. That is so that more traditional C pointer iteration style can be used as an alternative to using some counter based upon the "count".
Also not that the Perl print statements come before the C print statements! That of course has to be due some buffering weirdness, but I didn't figure out how to defeat that behaviour. Also for some reason, the API function, av_count() wasn't available on my version so a simple workaround calculation was used.
#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(_Edj
+e_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 thi
+s version
// sizeof(Edje_Message_String_Set) only has the integer,count of 8 b
+ytes
// 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 variab
+le
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);
}