FFI-C

 view release on metacpan or  search on metacpan

lib/FFI/C/Struct.pm  view on Meta::CPAN

package FFI::C::Struct;

use strict;
use warnings;
use FFI::C::Util;
use FFI::C::FFI ();
use Ref::Util qw( is_ref is_plain_arrayref );

# ABSTRACT: Structured data instance for FFI
our $VERSION = '0.15'; # VERSION


sub AUTOLOAD
{
  our $AUTOLOAD;
  my $self = shift;
  my $name = $AUTOLOAD;
  $name=~ s/^.*:://;
  if(my $member = $self->{def}->{members}->{$name})
  {
    my $ptr = $self->{ptr} + $member->{offset};

    if($member->{nest})
    {
      my $m = $member->{nest}->create($ptr,$self->{owner} || $self);
      FFI::C::Util::perl_to_c($m, $_[0]) if @_;
      return $m;
    }

    my $ffi = $self->{def}->ffi;

    if(defined $member->{count})
    {
      if(defined $_[0])
      {
        if(! is_ref $_[0])
        {
          my $index = shift;
          Carp::croak("$name Negative index on array member") if $index < 0;
          Carp::croak("$name OOB index on array member") if $index >= $member->{count};
          $ptr += $index * $member->{unitsize};
        }
        elsif(is_plain_arrayref $_[0])
        {
          my $array = shift;
          Carp::croak("$name OOB index on array member") if @$array > $member->{count};
          my $asize = @$array * $member->{unitsize};
          $ffi->function( FFI::C::FFI::memcpy_addr() => [ 'opaque', $member->{spec} . "[@{[ scalar @$array ]}]", 'size_t' ] => 'opaque' )
              ->call($ptr, $array, $asize);
          my @a;
          tie @a, 'FFI::C::Struct::MemberArrayTie', $self, $name, $member->{count};
          return \@a;
        }
        else
        {
          Carp::croak("$name tried to set element to non-scalar");
        }
      }
      else
      {
        my @a;
        tie @a, 'FFI::C::Struct::MemberArrayTie', $self, $name, $member->{count};
        return \@a;
      }
    }

    if(@_)



( run in 1.012 second using v1.01-cache-2.11-cpan-39bf76dae61 )