This works for dynamically allocating memory (an array of char):
SV * create_image(int size) { char * image; New(0,image,size,char); memset(image,CLEAR,size); return sv_setref_pv(newSViv(0),"image", (void *)image); }
void destroy_image(SV * p) { char * image = (char *) SvIV(SvRV(p)); Safefree(image); }
And to access the memory as an array of char:
void clear_image(SV * p,int size) { char * image = (char *) SvIV(SvRV(p)); memset(image,CLEAR,size); }
Yes, I had kept a copy of that from when you originally posted and was using that as a basis for my attempt. With some off-list assistance and the OOP example ('Soldier') in the cookbook, it's now working quite nicely. (First problem was that I was stupidly creating a reference to something that didn't exist - as Joe pointed out a little earlier today:-)
I would assume something similar would work for a struct, something along the lines of:
typedef struct { SV * suit; int value; } CARD;
SV * create_card(int size) { CARD * my_card; New(0,my_card,size,CARD); memset(my_card,CLEAR,size*sizeof(CARD)); return sv_setref_pv(newSViv(0),"card", (void *)my_card); }
I only wanted one card (with 'suit' and 'value' supplied as function arguments so I have:
SV * create_card(SV * s, int v) {
Card *cptr;
New(1, cptr, sizeof(Card), Card);
if(cptr == NULL) croak("Mem not allocated");
cptr->suit = s;
cptr->value = v;
return sv_setref_pv(newSViv(0), Nullch, cptr);
}which would allocate memory for an array of cards (a 'deck' so to speak), and return the pointer to the array. I would have done a function to create one card, but it would not have been any simpler. And for whatever reason, I have trouble getting Inline to properly recognize and bind functions that pass no params (int myfunc(void)).
Try writing it as 'int myfunc() {}' rather than 'int myfunc(void) {}'
And to hand out cards from Perl:
void deal_card(SV * p,SV * suit,int value) { CARD * my_card = (CARD *) SvIV(SvRV(p)); my_card->suit = suit; my_card->value = value; return; }
I'm not 100% sure on the "SvIV(SvRV(p))" part -- It's what works for an array of char.
Seems to work just fine for 'Card' and for the GMP library structs (which is what I'm really doing).
Incidentally, there's a current (small) thread on this subject on the XS mailing list where Nick Ing-Simmons offers the following:
----------------------------------------------- >Is it safe to store a pointer to a C struct in an SV?
Yes, provided the lifetime of the data pointed to is suitable.
> > MY_STRUCT my_struct; > sv = newSVuv((unsigned long) &my_struct); > SvIOK_only_UV(sv);
Your my_struct is on the stack in the XS function - memory gets reused when XS returns.
What I tend to do is put the struct in the string part of a SvPV
SV *sv = newSV(sizeof(MY_STRUCT));
MY_STRUCT *my_struct = (MY_STRUCT *) SvPVX(sv);> >and later on my_filter() can then access: > > (MY_STRUCT *) SvUVX(sv)
That would in my scheme be
MY_STRUCT *my_struct = (MY_STRUCT *) SvPVX(sv); -----------------------------------------------
I haven't digested that yet :-)
Thanks David, Joe.
Cheers, Rob
--
Any emails containing attachments will be deleted from my ISP's mail server before I even get to see them. If you wish to email me an attachment, please provide advance warning so that I can make the necessary arrangements.
