Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Exposing Perl objects in C

3 views
Skip to first unread message

JR Heisey

unread,
Mar 4, 2015, 12:30:02 PM3/4/15
to per...@perl.org
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.

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.

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.

Thanks,
J.R.

bulk 88

unread,
Mar 4, 2015, 9:00:02 PM3/4/15
to JR Heisey, per...@perl.org


> To: per...@perl.org
> Date: Wed, 4 Mar 2015 18:18:29 +0100
> From: jrhe...@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;
}

0 new messages