On Mon, 10 Apr 2006, Sergey Skvortsov wrote:

Igor Sysoev wrote:
On Thu, 6 Apr 2006, Igor Sysoev wrote:

is the effective way to return data from XS to perl without unnecessary
memory coping ? As I understand

1) if I return char*, then perl creates SV and copies the string to SV.

If you allocate *out with your own allocator (and *out must not be freed
with Safefree() on SV destruction) you can use another approach:

char *my_c_func(const char *in, STLEN len_in, STLEN *len_out)   {
        char *out;

        *len_out = len_in;      // or other pre-calculated value
        out = my_alloc(*len_out);       // sic!

        // process *in => *out

        return out;
}

MODULE = XXX
PROTOTYPES: DISABLE

void
myfunc(in)
  CODE:
  {
        STRLEN len_in, len_out;
        char *out;
        char *in = SvPV(ST(0), len_in);
        SV *res;

        out = my_c_func(in, len, &len_out);

        res = sv_newmortal();
        sv_upgrade(sv, SVt_PV);
        SvPOK_on(res);
        SvPV_set(res, out);
        SvLEN_set(res, len_out+1);
        SvCUR_set(res, len_out);
        SvFAKE_on(res);         // trick!!!
        SvREADONLY_on(res);     // FAKE/READONLY will be reset
                                // on string change/normalization
                                // and PVX will be copied to new
                                // allocated string

        ST(0) = res;
        XSRETURN(1);
   }

Thank you, Sergey. This is exactly what I need: I use own allocator
and my data should not be free()d by perl.

Fairly, there is even more speedup hacks. For example, you can use
TARG-macros, if you allocate string with Newx() call.

Could you explain in detail ?

By the way, is it possible to avoid creating my mortal SV and create just
perl SV ?


Igor Sysoev
http://sysoev.ru/en/

Reply via email to