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>>=3B To: perl-xs@= perl.org<br>>=3B Date: Wed=2C 4 Mar 2015 18:18:29 +0100<br>>=3B From: j= [email protected]<br>>=3B Subject: Exposing Perl objects in C<br>>= =3B <br>>=3B Hi=2C<br>>=3B <br>>=3B I have a collection of Perl objec= ts in an application.<br>>=3B I want a C program to have access to the da= ta in these objects.<br>>=3B The objects are implemented as a package<br>= >=3B <br>>=3B The C application wants an object handle with which it ca= n make C <br>>=3B function calls and pass the object handle.<br>>=3B <b= r>>=3B I have limited experience writing to the PerlApi=2C etc. I was hop= ing that <br>>=3B each perl SV has some unique identifier (UID). The goal= is to retrieve <br>>=3B the UID=2C pass it as an integer or void * so I = don't need to manage my <br>>=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>>=3B I realize I cou= ld create new SV * and increment the reference count.<br>>=3B I would the= n need to keep track of these SV pointers in order to clean <br>>=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>>=3B <br>>=3B I would hoping I could use a UID to create temp= orary SV * objects=2C <br>>=3B perform a data access then decrement the r= eference count.<br>>=3B <br>>=3B void get_dataInt(FOO * foo=2C int * va= lue)<br>>=3B {<br>>=3B // abbreviated Perl stack stuff<br>>=3B = SV * pOjbect =3D newSV_VooDoo((someVooDooCast)foo)=3B // a 32 bit value <br= >>=3B if I am lucky<br>>=3B XPUSHs(sv_2mortal(pObject))=3B<br>>=3B= PUTBACK=3B<br>>=3B count =3D call_method("getData"=2C G_EVAL | G_S= CALAR)=3B<br>>=3B <br>>=3B // error checking stuff<br>>=3B *val= ue =3D POPi=3B<br>>=3B }<br>>=3B <br>>=3B Or something conceptually l= ike that.<br>>=3B <br>>=3B With out this I need to allocate my own C ob= ject with which to capture a <br>>=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_--