in reply to Re^2: C types and SV's
in thread C types and SV's and unpack

First you make the C data buffer available as a PV to Perl, I think via newSvPV. Depending on the documentation on who owns the memory, you don't want the memory to be freed by Perl but by your library, see the documentation on how to tell Perl to not free your PV.

Then, you can use unpack to get at the raw numbers. This will likely use the same semantics as your C compiler, which should in this case be "good enough". Beware that this might break if you transport data between machines with differing endianness or word size:

my $bps = 32; my $fmt = 3; my %template = ( "32,3" => 'd',# A double-precision float in native format. "32,1" => 'I', "32,2, => 'i', # ... add the other formats as you need ); my $rawdata = get_raw_data_from_C_library(); my $t = $template{ "$bps,$fmt" } or die "Couldn't find an unpack template for $bps BPS, format $fmt +"; my @samples = unpack $template, $rawdata;

Replies are listed 'Best First'.
Re^4: C types and SV's
by blakew (Monk) on Jul 18, 2010 at 20:05 UTC
    Corion, you are the best. I think I've got it-
    #!/usr/bin/perl use strict; use warnings; use Inline 'C'; Inline->init; my $buffer_size = 36; # (6x6) print "Buffer size: $buffer_size\n"; my %template = ( "32,3" => 'f', "32,1" => 'I', "32,2" => 'i', "8,1" => 'c', "8,2" => 'C', # ... add the other formats as you need ); my $data; print "char* data:\n"; $data = get_char_buffer(); printf "Raw data %s\n", $data; print_buf( $data, 8, 1 ); # unsigned ints print "\nfloat* data:\n"; print_buf( get_float_buffer(), 32, 3 ); # floating point sub print_buf { my ( $rawdata, $bps, $fmt ) = @_; print "Ref count: " . get_ref_count( $rawdata ) . "\n"; my $t = $template{ "$bps,$fmt" } or die "Couldn't find an unpack template for $bps BPS, format +$fmt"; print "Template: $t\n"; my @samples = unpack( "${t}${buffer_size}", $rawdata ); print "Samples:\n@samples\n"; } 1; __DATA__ __C__ #define BUF_SIZE 36 SV* get_char_buffer() { void* buffer; SV* sv_buf; int i; buffer = malloc(sizeof(char) * BUF_SIZE); for (i = 65; i < 65 + BUF_SIZE; i++) { // printable chars ((char*)buffer)[i-65] = (char)i; } sv_buf = newSVpv(buffer,BUF_SIZE); free(buffer); return sv_buf; } SV* get_float_buffer() { void* buffer; SV* sv_buf; int i; buffer = malloc(sizeof(float) * BUF_SIZE); for (i = 1; i <= BUF_SIZE; i++) { ((float*)buffer)[i-1] = (float)(i + 0.5); } sv_buf = newSVpv(buffer,32*BUF_SIZE); free(buffer); return sv_buf; } int get_ref_count(SV* buf) { return (int)(SvREFCNT(buf)); }