RE: Exposing Perl objects in C

[email protected] (bulk 88) Wed, 4 Mar 2015 20:53:35 -0500
Newsgroups perl.xs
Message-ID <[email protected]>
--_c838cebe-21cb-4fb8-b6fb-f5781c2325f8_
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable



> To: [email protected]
> Date: Wed=2C 4 Mar 2015 18:18:29 +0100
> From: [email protected]
> Subject: Exposing Perl objects in C
>=20
> Hi=2C
>=20
> 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
>=20
> The C application wants an object handle with which it can make C=20
> function calls and pass the object handle.
>=20
> I have limited experience writing to the PerlApi=2C etc. I was hoping tha=
t=20
> each perl SV has some unique identifier (UID). The goal is to retrieve=20
> the UID=2C pass it as an integer or void * so I don't need to manage my=20
> 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=2C there is no re=
ason 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=20
> them up later.

Each refcount notch on a SV* must have an identifiable owner. In an XSUB=2C=
 the caller of the xsub owns the SV*. When you return SV*s on perl stack=2C=
 the mortal stack usually owns a notch. You may also return a package level=
 SV *=2C without ++=2C then mortaling it=2C since the package tree owns the=
 notch. In some cases=2C a non-perl-core C struct will be the owner of the =
SV* notch=2C in that case=2C it is upto you to destroy that C struct=2C and=
 its members (once of which is a SV *) at the correct time.

>=20
> I would hoping I could use a UID to create temporary SV * objects=2C=20
> perform a data access then decrement the reference count.
>=20
> void get_dataInt(FOO * foo=2C int * value)
> {
>    // abbreviated Perl stack stuff
>    SV * pOjbect =3D newSV_VooDoo((someVooDooCast)foo)=3B // a 32 bit valu=
e=20
> if I am lucky
>    XPUSHs(sv_2mortal(pObject))=3B
>    PUTBACK=3B
>    count =3D call_method("getData"=2C G_EVAL | G_SCALAR)=3B
>=20
>    // error checking stuff
>    *value =3D POPi=3B
> }
>=20
> Or something conceptually like that.
>=20
> With out this I need to allocate my own C object with which to capture a=
=20
> 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-D=
ispose-of-Temporaries and if that flowchart doesn't match what you need to =
do=2C explain the flowchart/callstack that your perl module will have to us=
. I rewrote your code with many comments.

void get_dataInt(FOO * foo=2C int * value)
{
//required=2C otherwise wont compile with perl threads
dTHX=3B
//required=2C otherwise you have no perl stack pointer to do a SOMETHING_PU=
SH_OSMETHING on
dSP=3B
//required (unless you know what you are doing and you
//probably dont as a beginner)=2C enter new perl scops
ENTER=3B
SAVETEMPS=3B
//X required since I (bulk88) dont know what the caller is=2C and therefore=
 cant
//compute minimum free space on perl stack=2C so use X to be safe
//also dont mess around with converting a number to a pointer through a loo=
kup
//table=2C make the object "handle" be the SV*=2C the C library wont care=
=2C its just
//an opaque pointer right?
XPUSHs((SV*)foo)=3B
PUTBACK=3B
count =3D call_method("getData"=2C G_EVAL | G_SCALAR)=3B
//you forgot SPAGAIN
SPAGAIN=3B
// error checking stuff
*value =3D POPi=3B
//pop the mortal and save stack scops we push earlier=2C this has to be don=
e
//after the POPi=2C since FREETMPS will free everything on our frame on Per=
l stack
FREETMPS=3B
LEAVE=3B
}

 		 	   		  =

--_c838cebe-21cb-4fb8-b6fb-f5781c2325f8_
Content-Type: text/html; charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

<html>
<head>
<style><!--
.hmmessage P
{
margin:0px=3B
padding:0px
}
body.hmmessage
{
font-size: 12pt=3B
font-family:Calibri
}
--></style></head>
<body class=3D'hmmessage'><div dir=3D'ltr'><br><br><div>&gt=3B To: perl-xs@=
perl.org<br>&gt=3B Date: Wed=2C 4 Mar 2015 18:18:29 +0100<br>&gt=3B From: j=
[email protected]<br>&gt=3B Subject: Exposing Perl objects in C<br>&gt=
=3B <br>&gt=3B Hi=2C<br>&gt=3B <br>&gt=3B I have a collection of Perl objec=
ts in an application.<br>&gt=3B I want a C program to have access to the da=
ta in these objects.<br>&gt=3B The objects are implemented as a package<br>=
&gt=3B <br>&gt=3B The C application wants an object handle with which it ca=
n make C <br>&gt=3B function calls and pass the object handle.<br>&gt=3B <b=
r>&gt=3B I have limited experience writing to the PerlApi=2C etc. I was hop=
ing that <br>&gt=3B each perl SV has some unique identifier (UID). The goal=
 is to retrieve <br>&gt=3B the UID=2C pass it as an integer or void * so I =
don't need to manage my <br>&gt=3B own list of Perl objects.<br><br>The SV*=
 is your UID. You can cast SV*s to void *s and back. The SV * should probab=
ly be the inner HV* of your ref to blessed hash (typical perl object). Unle=
ss 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=2C there is no reason on=
 why not to use the SV* as the opaque handle.<br><br>&gt=3B I realize I cou=
ld create new SV * and increment the reference count.<br>&gt=3B I would the=
n need to keep track of these SV pointers in order to clean <br>&gt=3B them=
 up later.<br><br>Each refcount notch on a SV* must have an identifiable ow=
ner. In an XSUB=2C the caller of the xsub owns the SV*. When you return SV*=
s on perl stack=2C the mortal stack usually owns a notch. You may also retu=
rn a package level SV *=2C without ++=2C then mortaling it=2C since the pac=
kage tree owns the notch. In some cases=2C a non-perl-core C struct will be=
 the owner of the SV* notch=2C in that case=2C it is upto you to destroy th=
at C struct=2C and its members (once of which is a SV *) at the correct tim=
e.<br><br>&gt=3B <br>&gt=3B I would hoping I could use a UID to create temp=
orary SV * objects=2C <br>&gt=3B perform a data access then decrement the r=
eference count.<br>&gt=3B <br>&gt=3B void get_dataInt(FOO * foo=2C int * va=
lue)<br>&gt=3B {<br>&gt=3B    // abbreviated Perl stack stuff<br>&gt=3B    =
SV * pOjbect =3D newSV_VooDoo((someVooDooCast)foo)=3B // a 32 bit value <br=
>&gt=3B if I am lucky<br>&gt=3B    XPUSHs(sv_2mortal(pObject))=3B<br>&gt=3B=
    PUTBACK=3B<br>&gt=3B    count =3D call_method("getData"=2C G_EVAL | G_S=
CALAR)=3B<br>&gt=3B <br>&gt=3B    // error checking stuff<br>&gt=3B    *val=
ue =3D POPi=3B<br>&gt=3B }<br>&gt=3B <br>&gt=3B Or something conceptually l=
ike that.<br>&gt=3B <br>&gt=3B With out this I need to allocate my own C ob=
ject with which to capture a <br>&gt=3B reference to the underlying Perl ob=
jects.<br><br>That code sample has many flaws<br><br>read the flowchart at =
<a href=3D"http://perldoc.perl.org/perlcall.html#Using-Perl-to-Dispose-of-T=
emporaries" target=3D"_blank">http://perldoc.perl.org/perlcall.html#Using-P=
erl-to-Dispose-of-Temporaries</a> and if that flowchart doesn't match what =
you need to do=2C explain the flowchart/callstack that your perl module wil=
l have to us. I rewrote your code with many comments.<br><br>void get_dataI=
nt(FOO * foo=2C int * value)<br>{<br>//required=2C otherwise wont compile w=
ith perl threads<br>dTHX=3B<br>//required=2C otherwise you have no perl sta=
ck pointer to do a SOMETHING_PUSH_OSMETHING on<br>dSP=3B<br>//required (unl=
ess you know what you are doing and you<br>//probably dont as a beginner)=
=2C enter new perl scops<br>ENTER=3B<br>SAVETEMPS=3B<br>//X required since =
I (bulk88) dont know what the caller is=2C and therefore cant<br>//compute =
minimum free space on perl stack=2C so use X to be safe<br>//also dont mess=
 around with converting a number to a pointer through a lookup<br>//table=
=2C make the object "handle" be the SV*=2C the C library wont care=2C its j=
ust<br>//an opaque pointer right?<br>XPUSHs((SV*)foo)=3B<br>PUTBACK=3B<br>c=
ount =3D call_method("getData"=2C G_EVAL | G_SCALAR)=3B<br>//you forgot SPA=
GAIN<br>SPAGAIN=3B<br>// error checking stuff<br>*value =3D POPi=3B<br>//po=
p the mortal and save stack scops we push earlier=2C this has to be done<br=
>//after the POPi=2C since FREETMPS will free everything on our frame on Pe=
rl stack<br>FREETMPS=3B<br>LEAVE=3B<br>}<br><br></div> 		 	   		  </div></b=
ody>
</html>=

--_c838cebe-21cb-4fb8-b6fb-f5781c2325f8_--