syphilis has asked for the wisdom of the Perl Monks concerning the following question:
Hi,
In perldoc Inline::C-Cookbook you'll find an "Object Oriented Inline" example. The following script (which works fine) is based on that example. I think the only changes I've made is to replace the strdup() calls (which are buggy) with savepv() calls - and I've added a Devel::Peek::Dump() call to reveal the innards of the objects being returned. Oh, yes ... and I've replaced malloc/free with New/Safefree:
Two questions:
1) Does/could it matter that the READONLY flag is missing ?
2) How do I re-instate that READONLY flag in the modified (more succinct) version of the new() function ?
I'm inclined to think that the answer to 2) is probably straightforward and that my attempts to find the answer have simply been plagued by my own idiocy. I tried the following rendition of new() but it, too, failed to turn on any readonly flags (according to Devel::Peek::Dump, anyway):
Update: Part of the attraction of Ken's rewrite is that it seems to lend itself more readily to typemapping (as regards the OUTPUT section of the typemap). But I'm unsure about that, too :-)
Cheers,
Rob
In perldoc Inline::C-Cookbook you'll find an "Object Oriented Inline" example. The following script (which works fine) is based on that example. I think the only changes I've made is to replace the strdup() calls (which are buggy) with savepv() calls - and I've added a Devel::Peek::Dump() call to reveal the innards of the objects being returned. Oh, yes ... and I've replaced malloc/free with New/Safefree:
Some time ago, Ken Williams suggested a more succinct rewrite of the new() function. (See http://www.mail-archive.com/inline@perl.org/msg01370.html for the post to which I refer.) In light of Ken's post I changed the new() function to this:use Devel::Peek; my $obj1 = Soldier->new('Benjamin', 'Private', 11111); my $obj2 = Soldier->new('Sanders', 'Colonel', 22222); my $obj3 = Soldier->new('Matt', 'Sergeant', 33333); for my $obj ($obj1, $obj2, $obj3) { print ($obj->get_serial, ") ", $obj->get_name, " is a ", $obj->get_rank, "\n"); } Dump($obj1); print "\n"; package Soldier; use Inline C => <<'END'; typedef struct { char* name; char* rank; long serial; } Soldier; SV* new(char* class, char* name, char* rank, long serial) { Soldier* soldier; New(42, soldier, 1, Soldier); SV* obj_ref = newSViv(0); SV* obj = newSVrv(obj_ref, class); soldier->name = savepv(name); soldier->rank = savepv(rank); soldier->serial = serial; sv_setiv(obj, (IV)soldier); SvREADONLY_on(obj); return obj_ref; } char* get_name(SV* obj) { return ((Soldier*)SvIV(SvRV(obj)))->name; } char* get_rank(SV* obj) { return ((Soldier*)SvIV(SvRV(obj)))->rank; } long get_serial(SV* obj) { return ((Soldier*)SvIV(SvRV(obj)))->serial; } void DESTROY(SV* obj) { Soldier* soldier = (Soldier*)SvIV(SvRV(obj)); Safefree(soldier->name); Safefree(soldier->rank); Safefree(soldier); } END __END__ Outputs: 11111) Benjamin is a Private 22222) Sanders is a Colonel 33333) Matt is a Sergeant SV = PVIV(0x2f5b8c) at 0x2f4940 REFCNT = 1 FLAGS = (PADBUSY,PADMY,ROK) IV = 0 RV = 0x2f3ca4 SV = PVMG(0x2febbc) at 0x2f3ca4 REFCNT = 1 FLAGS = (OBJECT,IOK,READONLY,pIOK) IV = 3143860 NV = 0 PV = 0 STASH = 0x45fca8 "Soldier" PV = 0x2f3ca4 "" CUR = 0 LEN = 0
That change, however, has a small effect on the output of the above script. Instead of getting FLAGS = (OBJECT,IOK,READONLY,pIOK) as per the above Devel::Peek::Dump(), I now get FLAGS = (OBJECT,IOK,pIOK). The READONLY flag that the original version of the script explicitly turned on is missing.SV* new(char* class, char* name, char* rank, long serial) { Soldier* soldier; New(42, soldier, 1, Soldier); soldier->name = savepv(name); soldier->rank = savepv(rank); soldier->serial = serial; return sv_setref_pv(newSViv(0), class, (void *)soldier); }
Two questions:
1) Does/could it matter that the READONLY flag is missing ?
2) How do I re-instate that READONLY flag in the modified (more succinct) version of the new() function ?
I'm inclined to think that the answer to 2) is probably straightforward and that my attempts to find the answer have simply been plagued by my own idiocy. I tried the following rendition of new() but it, too, failed to turn on any readonly flags (according to Devel::Peek::Dump, anyway):
FWIW, I've long been using the technique that appears in the Inline::C Cookbook ... and I'm starting to wonder whether I ought to switch to using Ken's suggested succinctification.SV* new(char* class, char* name, char* rank, long serial) { Soldier* soldier; SV *ret, *temp = newSViv(0); New(42, soldier, 1, Soldier); soldier->name = savepv(name); soldier->rank = savepv(rank); soldier->serial = serial; ret = sv_setref_pv(temp, class, (void *)soldier); SvREADONLY_on(temp); SvREADONLY_on(ret); return ret; }
Update: Part of the attraction of Ken's rewrite is that it seems to lend itself more readily to typemapping (as regards the OUTPUT section of the typemap). But I'm unsure about that, too :-)
Cheers,
Rob
Back to
Seekers of Perl Wisdom