> 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;
}

                                          

Reply via email to