> To: perl-xs@perl.org > Date: Wed, 4 Mar 2015 18:18:29 +0100 > From: jrhei...@synaptics.com > Subject: Exposing Perl objects in C > > Hi, > > I have a collection of Perl objects in an application. > I want a C program to have access to the data in these objects. > The objects are implemented as a package > > The C application wants an object handle with which it can make C > function calls and pass the object handle. > > I have limited experience writing to the PerlApi, etc. I was hoping that > each perl SV has some unique identifier (UID). The goal is to retrieve > the UID, pass it as an integer or void * so I don't need to manage my > own list of Perl objects.
The SV* is your UID. You can cast SV*s to void *s and back. The SV * should probably be the inner HV* of your ref to blessed hash (typical perl object). Unless your C library is so badly designed that a plugin's object handle/opaque pointer must be 16 or 32 bits on a 64 bit machine, there is no reason on why not to use the SV* as the opaque handle. > I realize I could create new SV * and increment the reference count. > I would then need to keep track of these SV pointers in order to clean > them up later. Each refcount notch on a SV* must have an identifiable owner. In an XSUB, the caller of the xsub owns the SV*. When you return SV*s on perl stack, the mortal stack usually owns a notch. You may also return a package level SV *, without ++, then mortaling it, since the package tree owns the notch. In some cases, a non-perl-core C struct will be the owner of the SV* notch, in that case, it is upto you to destroy that C struct, and its members (once of which is a SV *) at the correct time. > > I would hoping I could use a UID to create temporary SV * objects, > perform a data access then decrement the reference count. > > void get_dataInt(FOO * foo, int * value) > { > // abbreviated Perl stack stuff > SV * pOjbect = newSV_VooDoo((someVooDooCast)foo); // a 32 bit value > if I am lucky > XPUSHs(sv_2mortal(pObject)); > PUTBACK; > count = call_method("getData", G_EVAL | G_SCALAR); > > // error checking stuff > *value = POPi; > } > > Or something conceptually like that. > > With out this I need to allocate my own C object with which to capture a > reference to the underlying Perl objects. That code sample has many flaws read the flowchart at http://perldoc.perl.org/perlcall.html#Using-Perl-to-Dispose-of-Temporaries and if that flowchart doesn't match what you need to do, explain the flowchart/callstack that your perl module will have to us. I rewrote your code with many comments. void get_dataInt(FOO * foo, int * value) { //required, otherwise wont compile with perl threads dTHX; //required, otherwise you have no perl stack pointer to do a SOMETHING_PUSH_OSMETHING on dSP; //required (unless you know what you are doing and you //probably dont as a beginner), enter new perl scops ENTER; SAVETEMPS; //X required since I (bulk88) dont know what the caller is, and therefore cant //compute minimum free space on perl stack, so use X to be safe //also dont mess around with converting a number to a pointer through a lookup //table, make the object "handle" be the SV*, the C library wont care, its just //an opaque pointer right? XPUSHs((SV*)foo); PUTBACK; count = call_method("getData", G_EVAL | G_SCALAR); //you forgot SPAGAIN SPAGAIN; // error checking stuff *value = POPi; //pop the mortal and save stack scops we push earlier, this has to be done //after the POPi, since FREETMPS will free everything on our frame on Perl stack FREETMPS; LEAVE; }