Steve Hay wrote:
What's the best way to have an XSUB return a string (char *) when the caller doesn't know how big that string will be?

In C a function can't return a pointer to a function-static variable, but in Perl you can get away with a function returning a reference to a function-scoped lexical variable.

Can you do (fake) this sort of thing in an XSUB?

Presumably, if I malloced the space that I'm "returning a pointer to" then it needs freeing up afterwards, but not before Perl has copied it somewhere! Is a CLEANUP section good for that?

As a (silly) test, the following XSUB seems to work, but I'd just like to check that this is alright.

   char *
   hello()
       PREINIT:
           char    *text;

       CODE:
           Newz(0, text, 13, char);
           strcpy(text, "Hello, world");
           RETVAL = text;

       OUTPUT:
           RETVAL

       CLEANUP:
           Safefree(text);

It's a cheat really, because the return value is not a pointer to "local data" -- it's a pointer to a copy of it, the malloced local data itself being freed again -- but at least the caller doesn't have to provide the space for the data to be copied to.

Is there a better way to have a "Perlish" calling style like

$text = my_xsub();

when the caller doesn't know in advance how big that $text is going to be?


Not sure if what I'm doing classifies as 'helping', 'hindering', or 'hijacking' .... or all/some/none of the above.


But in Inline::C all you'd have to write to replicate the above is:

SV* hello() {return newSVpv("Hello World", 0);}

That produces an XS file that looks like this:
-----------------------------------------------
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "INLINE.h"

SV * hello() {
     return newSVpv("Hello World", 0);
     }


MODULE = try_pl_e5a4 PACKAGE = main


PROTOTYPES: DISABLE


SV * hello () ----------------------------------------------

'INLINE.h' simply defines the inline stack macros, which aren't being used in the above code, so I don't think it's serving any useful purpose - and could be removed from the inclusions.

I don't know XS (only Inline C) but the above demonstrates (I hope) that you can achieve what you want without any dynamic memory allocation, and without using the stack as per Tassilo's example. Mind you, I have no problem with using the stack - it seems to work just as efficiently as returning an SV* and, of course, accommodates the returning of multiple values.

I know even less about 'CLEANUP' - but I would expect it to be better to Safefree() in the 'CODE' section.

That's not a problem if hello() returns an SV* rather than a char*.

Something like:

-------------------------
   SV *
   hello()
       PREINIT:
           char    *text;
           SV      *ret;

       CODE:
           Newz(0, text, 13, char);
           strcpy(text, "Hello, world");
           ret = newSVpv(text, 0);
           Safefree(text);
           RETVAL = ret;
------------------------

Perl takes care of the cleanup of the SV* ret.
Btw, the second arg to 'newSVpv()' can either be the length of the string or '0' (in which case perl works out how big it has to be).


Hth.

Cheers,
Rob



--
Any emails containing attachments will be deleted from my ISP's mail server before I even get to see them. If you wish to email me an attachment, please provide advance warning so that I can make the necessary arrangements.




Reply via email to