Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Re: Tie::PureDB is out (thanks/PV)

by tye (Sage)
on Apr 10, 2003 at 15:55 UTC ( [id://249654]=note: print w/replies, xml ) Need Help??


in reply to Tie::PureDB is out
in thread panic: leave_scope inconsistency. (need help creating Tie::PureDB)

Thanks for the notes on proper allocation/free and converting between pointers and integers.

The approach I outlined is very similar to T_PTROBJ, both of which are about the best you can do (which isn't very good in my book) if you need to have Perl deal with data structures that Perl does not allocate.

Since you can use Safefree/New, then you are allocating the space and you can have a better interface by having Perl allocate the space instead.

SV * xs_new( ... ) CODE: size_t len= number_of_bytes_needed(); sv_grow( RETVAL, len ); // "malloc" void *buf= SvPV( RETVAL ); size_t used= constructor( buf, len, ... ); // Tell Perl how much of the buffer is actually in use: SvCUR_set( RETVAL, used );
Then you end up with a Perl scalar that contains a string value which is the contents of the buffer you allocated and Perl will be happy to free() it when it needs to and you don't even need a DESTROY method for that anymore. You can also access the buffer data directly from Perl now in case there are simple things you want to do that don't really require that XS code be written.

You can get the pointer to this buffer by simply using "char *" arguments in other XS functions.

And if you want a destroy method for other reasons, then I'd still do the bless and DESTROY in Perl code rather than in XS.

Be aware that passing this string value around directly in Perl can easily result in the value being copied (a new buffer malloc()d and the data copied from the old buffer to the new buffer) and that you can modify the buffer from Perl code such that Perl decides to realloc() the buffer which can relocate it in memory (and that both of these things can invalidate some types of data such a buffers that contain pointers into themselves).

Note that the value is not copied when you use the string as an argument to a function but that typical Perl functions include my $buf= shift(@_); or my( $buf, ... )= @_; which is where the copy takes place. So using the string directly in an XS function with a parameter type of "char *" works great.

I realize that PodMaster probably knows most or all of this, but I include this information for others that might read this node.

So you might want to wrap this string up as an object so passing around the object will just be copying references to the string (or references to some data structure that contains the string) and the string itself won't get copied.

Doing that means that you have an extra dereference required in your methods. You can do that in Perl, but if that is the only bit of "Perl written in C" that you need for that method, you might just do it all in XS. The big problems with writing "Perl in C" for XS is if you are creating things on the stack (everyone gets the mortal/refcount stuff wrong even though it isn't that complicated/confusing if you really get your mind around it) or trying to deal with Perl variables that users pass to you (XS code only deals with very vanilla variables and simply breaks in the face of tie or magic or a need for autovivification, etc. -- I've been thinking about croaking on "thinkfirst" in my XS code in future).

                - tye

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://249654]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (4)
As of 2024-04-16 17:36 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found