use strict;
use warnings;
package C::Blocks::Types;
our $VERSION = '0.42';
$VERSION = eval $VERSION;
# XXXXXXXX use Sub::Exporter for greater granularity and control???
# The purpose of this package is to provide short type names that are
# associated with the lengthy package names:
use constant {
# floating point
NV => 'C::Blocks::Type::NV',
double => 'C::Blocks::Type::double',
float => 'C::Blocks::Type::float',
# basic integer types
IV => 'C::Blocks::Type::IV',
short => 'C::Blocks::Type::short',
Int => 'C::Blocks::Type::int',
long => 'C::Blocks::Type::long',
UV => 'C::Blocks::Type::UV',
uint => 'C::Blocks::Type::uint',
ushort => 'C::Blocks::Type::ushort',
ulong => 'C::Blocks::Type::ulong',
# array types
double_array => 'C::Blocks::Type::double_array',
float_array => 'C::Blocks::Type::float_array',
int_array => 'C::Blocks::Type::int_array',
char_array => 'C::Blocks::Type::char_array',
};
use Exporter qw(import);
our @EXPORT_OK = qw(NV double float IV short Int long UV uint
double_array float_array int_array char_array);
our %EXPORT_TAGS = (
basic => [qw(short Int long ushort uint ulong float double)],
perl_num => [qw(NV IV UV)],
all => [@EXPORT_OK],
);
########################################################################
package C::Blocks::PerlAPI::Type;
########################################################################
sub c_blocks_init_cleanup {
my ($package, $C_name, $sigil_type, $pad_offset) = @_;
my $data_type = $package->data_type;
my $getter = $package->getter;
my $setter = $package->setter;
my $init_code = "$sigil_type * SV_$C_name = ($sigil_type*)PAD_SV($pad_offset); "
. "$data_type $C_name = $getter(SV_$C_name); ";
my $cleanup_code = "$setter(SV_$C_name, $C_name);";
return ($init_code, $cleanup_code);
}
########################################################################
# Floating point
########################################################################
package C::Blocks::Type::NV;
our @ISA = qw(C::Blocks::PerlAPI::Type);
sub data_type { 'NV' }
sub getter { 'SvNV' }
sub setter { 'sv_setnv' }
package C::Blocks::Type::double;
our @ISA = qw(C::Blocks::Type::NV);
sub data_type { 'double' }
package C::Blocks::Type::float;
our @ISA = qw(C::Blocks::Type::NV);
sub data_type { 'float' }
########################################################################
# Signed Integers
########################################################################
package C::Blocks::Type::IV;
our @ISA = qw(C::Blocks::PerlAPI::Type);
sub data_type { 'IV' }
sub getter { 'SvIV' }
sub setter { 'sv_setiv' }
package C::Blocks::Type::int;
our @ISA = qw(C::Blocks::Type::IV);
sub data_type { 'int' }
package C::Blocks::Type::short;
our @ISA = qw(C::Blocks::Type::IV);
sub data_type { 'short' }
package C::Blocks::Type::long;
our @ISA = qw(C::Blocks::Type::IV);
sub data_type { 'long' }
########################################################################
# Unsigned Integers
########################################################################
package C::Blocks::Type::UV;
our @ISA = qw(C::Blocks::PerlAPI::Type);
sub data_type { 'UV' }
sub getter { 'SvUV' }
sub setter { 'sv_setuv' }
package C::Blocks::Type::uint;
our @ISA = qw(C::Blocks::Type::UV);
sub data_type { 'unsigned int' }
package C::Blocks::Type::ushort;
our @ISA = qw(C::Blocks::Type::UV);
sub data_type { 'unsigned short' }
package C::Blocks::Type::ulong;
our @ISA = qw(C::Blocks::Type::UV);
sub data_type { 'unsigned long' }
########################################################################
# Arrays
########################################################################
package C::Blocks::Type::double_array;
sub data_type { 'double' }
sub c_blocks_init_cleanup {
my ($package, $C_name, $sigil_type, $pad_offset) = @_;
my $data_type = $package->data_type;
my $init_code = join(";\n",
"$sigil_type * SV_$C_name = ($sigil_type*)PAD_SV($pad_offset)",
"STRLEN length_$C_name",
"$data_type * $C_name = ($data_type*)SvPVbyte(SV_$C_name, length_$C_name)",
"length_$C_name /= sizeof($data_type)",
'',
);
return $init_code;
}
package C::Blocks::Type::float_array;
our @ISA = qw(C::Blocks::Type::double_array);
sub data_type { 'float' }
package C::Blocks::Type::int_array;
our @ISA = qw(C::Blocks::Type::double_array);
sub data_type { 'int' }
package C::Blocks::Type::char_array;
our @ISA = qw(C::Blocks::Type::double_array);
sub data_type { 'char' }
# Other types:
# int2ptr
# uint2ptr
__END__
=head1 NAME
C::Blocks::Types - type classes for basic C data types for C::Blocks
=head1 VERSION
This documentation is for v0.40_1
=head1 SYNOPSIS
use C::Blocks;
use C::Blocks::Types qw(double double_array Int);
# Generate some synthetic data;
my @data = map { rand() } 1 .. 10;
print "data are @data\n";
# Pack this data into a C array
my double_array $points = pack 'd*', @data;
# Calculate the rms (root mean square)
my double $rms = 0;
cblock {
for (int i = 0; i < length_$points; i++) {
$rms += $points[i]*$points[i];
}
$rms = sqrt($rms / length_$points);
}
print "data rms is $rms\n";
# Note that Int is capitalized, unlike the other type names
my Int $foo = 4;
cblock {
printf("$foo is %d\n", $foo);
}
=head1 DESCRIPTION
L<C::Blocks> lets you intersperse blocks of C code directly among your
Perl code. To help facilitate the interchange of C and Perl data, you
can indicate that your Perl variable has an associated type package.
This is discussed in L<C::Blocks/TYPES>. The purpose of this package is
to provide type packages, and short names, for basic C data types like
L<double> and L<short>, as well as rudimentary packed arrays.
... must document provided types as well as "length_" variables.