in reply to Re: Perl XS: garbage-collecting my malloc'd buffer
in thread Perl XS: garbage-collecting my malloc'd buffer

I'd think that ($len,$buf)= my_xs_func(...) would often be inconvenient and thus not very "perlish" (Perl places a large value on programmer convenience) and I consider the interface provided by Perl's own read and related functions to be "perlish". So I'd go with the original design.

You should also note that your code assumes that the buffer gets populated with a '\0'-terminated string. [ Update: as does the original node's second code block, so that is probably a safe assumption (: ]

If I was sure that the values being created were very unlikely to be very large and that they didn't contain internal pointers, then I might go with copying the generated value but only if the integer returned by the function was just the length so I could use:

my $result= my_xs_funct($struct,$len); my $outlen= length($result);
Mileage will certainly vary.

                - tye

Replies are listed 'Best First'.
Re: Re^2: Perl XS: garbage-collecting my malloc'd buffer (perlish?)
by Elian (Parson) on Mar 03, 2003 at 17:44 UTC
    I didn't put that much thought into the process, though I really despise routines that alter their parameters needlessly. (And in this case it really seems that way) The XS code could potentially be cleaned up some, with the length getting subsumed into the length of the resulting SV string, which'd be the better way to do it, I expect. Checking the want status is also reasonable, and having different returns based on it. Either of those (multiple returns, or want-based returns) are 'better' than altering the input, or at least so go my preferences.

    Still, I very much mistrust code that uses returned buffers from libraries. While it's OK in some cases, I've found myself burned often enough with library buffer reuse or freeing at odd times that I much prefer making a copy of the data. It's very rarely large enough to be a performance issue, and those cases can be handled specially. It's generally better, especially for folks who aren't used to writing XS code, to make the copy and optimize it away later, since that gets them the safe case by default.

      No, you can't get Perl to use buffers allocated by other libraries (I don't think it is OK in any cases -- and I've tried and been impressed with how hard Perl makes it to even use magic to get such working). But I wasn't doing that. I was having Perl allocate the buffer and having the C routine use it.

      If you are worried about the C routine (or some other routine from that library) reallocating or free()ing the buffer passed to it, then you'll have problems in those cases even with your solution. To avoid that you'd have to copy the data out of the Perl buffer before calling subsequent routines (something that isn't even shown to be happening). If the C routine in question reallocated or freed the buffer, then the interface to the C routine would simply be broken and there would be no safe way to use it. So I don't see any problem with my approach.

      I despise XS code that is complex. If I wanted to go to the point of checking wantarray etc. then I'd have a Perl subroutine wrapper for the XS code and do such interface massaging there rather than in the XS code. (:

                      - tye
        No, you can't get Perl to use buffers allocated by other libraries
        Oh, sure you can. It's not that big a deal, though you need to mark the SV as readonly or throw some TIE magic on it to make sure the buffer doesn't go moving around without something being able to handle it. You need to be mildly careful to make sure the code's not too fragile, but that's about it.

        As for complex XS code... It's always been my view that if you're bopping back and forth between C and perl, you're making a mistake. The XS code should handle everything it needs to, and should present a simple interface. Dealing with perl's stack, return values, hashes, and other things isn't at all difficult unless you make it so, and it's been my experience that trying to not do things in XS is the easiest way to make things far more difficult than you have to.

        The C/perl boundary should be crossed only once, and the presented interface should be clean, proper, and perlish. Fear or dislike of XS or C is no reason to not do things properly, because to do so leads to messy and buggy code.

        If you had to drop to XS, you might as well do it right, rather than do a half-assed hack job that you patch up in a wrapper perl routine.