Jump to: main text

Datatype examples from Inline::SLang

The following code and examples can be found in the Inline::SLang distribution available from CPAN. The output was created using version 1.00 of the module, using the PDL support, together with version 1.4.9 of the S-Lang library.

It is no use being able to call S-Lang functions if you can not deal with the values it returns. Simple types such as scalars (integers, reals, and strings) are handled using native types wherever possible. So-called "opaque" types - in general those defined by a module but it does include several of the standard types defined by the S-Lang interpreter - are converted to Perl objects and should be left alone.

In the examples below we show a number of ways that data can be moved back and forth between S-Lang and Perl. For information on specific types of conversion please see the following examples pages: arrays; associative arrays; and structures. The type support is described in the Inline::SLang::Types documentation that comes with the module.

Basic datatypes

#
# Examples taken from the introduction to the
# Inline::SLang::Types documentation
#

use Inline SLang => Config => BIND_SLFUNCS => [ "vmessage" ];
use Inline SLang;
use Math::Complex;

# the S-Lang Complex_Type variable is automatically converted
# to a Math::Complex object in Perl.
#
my $val = makecplx();
print "Perl has been sent $val\n";

# the multiplication is done using Math::Complex objects and
# the result then converted to a S-Lang Complex_Type variable,
# since vmessage is a S-Lang function [the %S means convert
# the variable to its string representation]
#
vmessage( "S-Lang has been sent %S", $val * cplx(0,1) );

my $type = typecplx($val);
print "And the S-Lang datatype is $type\n";
print "        Perl object        " .  $type->typeof . "\n";

__END__
__SLang__

define makecplx() { return 3 + 4i; }
define typecplx(cval) { return typeof(cval); }

which, when run, produces

Perl has been sent 3+4i
S-Lang has been sent (-4 + 3i)
And the S-Lang datatype is Complex_Type
        Perl object        DataType_Type

The typeof function

# want to bind the typeof function
#
use Inline SLang;

my $a0 = getfoo(0);
my $a1 = getfoo(1);
my $a2 = getfoo(2);

print "\nIn Perl:\n";
printf "typeof(foo[0]) = %s\n", $a0->typeof;
printf "typeof(foo[1]) = %s\n", $a1->typeof;
printf "typeof(foo[2]) = %s\n",
  defined($a2) ? $a2->typeof : "undef";

__END__
__SLang__

variable foo = Any_Type [3];
foo[0] = "a string";
foo[1] = 23;

define getfoo(x) { return foo[x]; }

message( "In S-Lang:" );
vmessage( "typeof(foo[0]) = %s", string(typeof(foo[0])) );
vmessage( "typeof(foo[1]) = %s", string(typeof(foo[1])) );
vmessage( "typeof(foo[2]) = %s", string(typeof(foo[2])) );

which, when run, produces

In S-Lang:
typeof(foo[0]) = Any_Type
typeof(foo[1]) = Any_Type
typeof(foo[2]) = Null_Type

In Perl:
typeof(foo[0]) = Any_Type
typeof(foo[1]) = Any_Type
typeof(foo[2]) = undef

Note: the Null_Type variable in S-Lang gets converted to a Perl undef.

Using references

use Inline SLang;

my $ref = getfoo();

print "\$ref is a " . ref($ref) . " object\n";
print "And when printed as a string = $ref\n";

printfoo($ref);
changefoo($ref,"no it isn't");
printfoo($ref);

__END__
__SLang__

variable foo = "this is a string";
define getfoo() { return &foo; }
define printfoo(x) { () = printf( "foo = [%s]\n", @x ); }
define changefoo(x,y) { @x = y; }

which, when run, produces

$ref is a Ref_Type object
And when printed as a string = Ref_Type
foo = [this is a string]
foo = [no it isn't]

What types are available?

The INFO option of the Inline module can be used to find out, amongst other things, what data types from S-Lang are recognised by the module. The following example:

#
# Use this via 'perl -Mblib -MInline=info example/info.pl'
#

use Inline SLang;
# let's not actually do anything

__END__
__SLang__

typedef struct { foo, bar } FooBarStruct_Type;

variable foobar = "a string";
define foo()  { return foobar; }
define bar(x) { foobar = x; }

produces the following output when the '-MInline=info' option is added to the Perl interpreter:

<-----------------------Information Section----------------------------------->

Information about the processing of your Inline SLang code:

Your source code needs to be compiled. I'll use this build directory:
/data/dburke2/www/perl-slang/examples/_Inline/build/info_pl_9cef

and I'll install the executable as:
/data/dburke2/www/perl-slang/examples/_Inline/lib/auto/info_pl_9cef/info_pl_9cef.sldat

Configuration details
---------------------

Version of S-Lang: 1.4.9
Perl module version is 1.00 and supports PDL

The following S-Lang types are recognised:
 Int32_Type UInteger_Type _IntegerP_Type
 FooBarStruct_Type[Struct_Type] Int_Type Struct_Type ULong_Type
 FD_Type Long_Type Float_Type Array_Type UInt32_Type File_Type
 UInt_Type UChar_Type UShort_Type Double_Type Float64_Type Int16_Type
 Float32_Type Null_Type Integer_Type BString_Type Char_Type
 Undefined_Type Short_Type Any_Type Assoc_Type Ref_Type Complex_Type
 String_Type UInt16_Type DataType_Type

The following S-Lang namespaces have been bound to Perl:

  2 functions from namespace Global are bound to package main
	bar()
	foo()


<-----------------------End of Information Section---------------------------->

Further messing around with types


In this somewhat convoluted example, the S-Lang routine bar() returns a number of variables which we then inspect with the printval() routine (written in Perl). It is just intended to show that you can convert arbitrarily complex data structures between Perl and S-Lang - assuming that the individual components can be converted that is!

use strict;
use Inline 'SLang';
use Data::Dumper;

# this is not meant to be a robust, general purpose, printing routine!
sub printval ($;$);
sub printval ($;$) {
  my $x     = shift;
  my $depth = shift || 0;

  my $ref   = ref($x);
  my $spacer = '  ' x $depth;
  unless ( $ref ) {
    print "${spacer}Scalar: $x\n";
    return;
  }

  if ( $ref eq "ARRAY" ) {
    print "${spacer}Array:\n";
    print "${spacer}  " . Dumper($x) . "\n";
    return;
  }

  if ( $ref eq "Struct_Type" ) {
    print "${spacer}Struct_Type:\n";
    while ( my ( $field, $val ) = each %{$x} ) {
      print "${spacer}  field $field contains\n";
      printval( $val, $depth+2 );
    }
    return;
  }

  if ( $ref eq "Assoc_Type" ) {
    my $type = $x->_typeof;
    print "${spacer}Assoc_Type [$type]:\n";
    while ( my ( $field, $val ) = each %{$x} ) {
      print "${spacer}  key '$field' contains\n";
      printval( $val, $depth+2 );
    }
    return;
  }

  print "${spacer}Object: $x\n";

} # sub: printval

foreach my $perlval ( bar() ) { printval($perlval); }

__END__
__SLang__

define bar () {
  variable x = struct { foo, bar };
  x.foo = 1;
  x.bar = Assoc_Type [String_Type];
  x.bar["a a"]     = "a string";
  x.bar["flibble"] = "another string";
  return ( 1, 2.3, ["an","array","of strings"], x, 4-3i );
}

The output of this code is:

Scalar: 1
Scalar: 2.3
Array:
  $VAR1 = [
          'an',
          'array',
          'of strings'
        ];

Struct_Type:
  field foo contains
    Scalar: 1
  field bar contains
    Assoc_Type [String_Type]:
      key 'a a' contains
        Scalar: a string
      key 'flibble' contains
        Scalar: another string
Object: 4-3i