in reply to Need to pass an unsigned char array from an xsub back to Perl

Your code is somewhat confusing as to whether you want to return the unsigned char[16] as a Perl array/list (16 individual values), or as a scalar (Perl string of length 16).

Assuming the latter, I think you're approaching things in a much too complicated way.  Simply create a char[16] buffer in C, let XSessionID() fill it, and place a copy of it in an SV, which you then return:

#!/usr/bin/perl -wl use strict; use Inline C => <<'END_C'; SV* GenerateSessionID() { char uuid[16]; // buffer // fill buffer, i.e. mimic your XSessionID() int i; for (i=0; i<16; i++) { uuid[i] = 0xA0 + i; } return newSVpvn(uuid, 16); } END_C my $uuid = GenerateSessionID(); print join ' ', unpack("(H2)*", $uuid);

Output:

$ ./962624.pl a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af

Not using Inline::C (i.e. using a normal XSUB instead), this should translate to something like

SV * GenerateSessionID() PREINIT: char uuid[16]; CODE: XSessionID((uuid_t*)uuid); RETVAL = newSVpvn(uuid, 16); OUTPUT: RETVAL

Or, if you want to use PPCODE:

void GenerateSessionID() PREINIT: char uuid[16]; PPCODE: XSessionID((uuid_t*)uuid); ST(0) = newSVpvn(uuid, 16); sv_2mortal(ST(0)); XSRETURN(1);

Replies are listed 'Best First'.
Re^2: Need to pass an unsigned char array from an xsub back to Perl
by Anonymous Monk on Mar 30, 2012 at 17:19 UTC
    Thank you so much for the quick reply. Indeed, your solution is very elegant. I am a newbie in xsubb. I did use the second method.
    PREINIT: unsigned char uuid_arr[16]; CODE: char convert_arr[33]; int i; XGenerateSessionID((uuid_t*) &uuid_arr); memset(convert_arr,'\0',33); for(i=0; i< 16; i++){ snprintf(&convert_arr[i*2], sizeof(convert_arr)-(i*2), "%02X" +, uuid_arr[i]); } RETVAL = newSVpvn(convert_arr,33); OUTPUT: RETVAL
    If I had not converted the unsigned char back to char, the compiler complains of signedness.
Re^2: Need to pass an unsigned char array from an xsub back to Perl
by bulk88 (Priest) on Apr 01, 2012 at 16:57 UTC
    Or, if you want to use PPCODE:
    void GenerateSessionID() PREINIT: char uuid[16]; PPCODE: XSessionID((uuid_t*)uuid); ST(0) = newSVpvn(uuid, 16); sv_2mortal(ST(0)); XSRETURN(1);
    Thats quite bloated. This is less bloated.
    void GenerateSessionID() PREINIT: char uuid[16] = {0); //zero fill PPCODE: XSessionID((uuid_t*)uuid); PUSHs(sv_2mortal((newSVpvn(uuid, 16)));
    Also the OP might want to zero his UUID since we are not checking the return value of XSessionID to determine failure.