Structure 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 together with version 1.4.9 of the S-Lang library.
S-Lang structures are converted to hash references in Perl, as shown below. The datatypes example page may also be useful. The support for structures is described in the Inline::SLang::Struct documentation that comes with the module.
Converting structures
Actually, structures are not converted to a hash reference but to a Perl object which behaves like it is a reference to a hash array. The differences to an actual hash array are:
- The order of the keys - as returned by foreach, each, keys, ... - is not random but matches the order of the fields in the S-Lang structure.
- Keys can not be added to, or removed from, the object.
In most cases you should not need to worry about these differences.
use strict; use Inline 'SLang'; my $s = get_struct("foo"); print "get_struct() returned a $s - and ref(\$s) = " . ref($s) . "\n\n"; print "Structure contents:\n"; # you can treat $s as a reference to a hash array in most respects, except: # - the order of the keys in the array matches that of the # original S-Lang structure # while ( my ( $key, $value ) = each %{$s} ) { print " key $key\t has a value of $value\n"; } print "\n"; $$s{afield} = 'a changed field value'; print "Key afield now has a value of [$$s{afield}]\n"; __END__ __SLang__ define get_struct(x) { variable out = struct { xfield, afield }; out.xfield = x; out.afield = strlen(x); return out; }
If the above is run then it will produce the following output.
get_struct() returned a Struct_Type - and ref($s) = Struct_Type Structure contents: key xfield has a value of foo key afield has a value of 3 Key afield now has a value of [a changed field value]
If you try to access (read or write) a field that does not exist then the Perl code will croak with an error message. As an example, if the previous code had included:
print "Key x has a value of [$$s{x}]\n";
then the program would have terminated with the error
Error: field 'x' does not exist in this Struct_Type structure
It is analogous to S-Lang's Invalid Parameter: struct has no field named x error message.
If you are wondering how "named" structures - i.e. those created by S-Lang's typedef struct { ... } ... statement - are handled, then the answer is that they are also converted to an object which can be treated as a hash reference. This object is a subclass of the Perl Struct_Type class and has a name that matches that given to it in the typedef statement.
To illustrate this we repeat the above code but this time using a typedef-ed structure.
use strict; use Inline 'SLang'; my $s = get_struct("foo"); print "get_struct() returned a $s - and ref(\$s) = " . ref($s) . "\n\n"; print "Structure contents:\n"; while ( my ( $key, $value ) = each %{$s} ) { print " key $key\t has a value of $value\n"; } print "\n"; $$s{afield} = 'a changed field value'; print "Key afield now has a value of [$$s{afield}]\n"; __END__ __SLang__ typedef struct { xfield, afield } Example_Struct; define get_struct(x) { variable out = @Example_Struct; out.xfield = x; out.afield = strlen(x); return out; }
which produces:
get_struct() returned a Example_Struct - and ref($s) = Example_Struct Structure contents: key xfield has a value of foo key afield has a value of 3 Key afield now has a value of [a changed field value]
Using "simple" structures
use Inline 'SLang' => <<'EOS'; variable runtime = time(); typedef struct { x, time } xTime_Struct; define ret1(x) { variable y = struct { x, time }; y.x = x; y.time = runtime; return y; } define ret2(x) { variable y = @xTime_Struct; y.x = x; y.time = runtime; return y; } EOS # first with a normal structure my $s1 = ret1( "struct example" ); print "ret1() returned a $s1\n"; printf "Is it a structure? [%d]\n", $s1->is_struct_type; printf "With keys/fields [ %s ]\n", join( ", ", keys(%$s1) ); print " s.x = $$s1{x}\n"; print " s.time = $$s1{time}\n"; # and then with a "named" structure my $s2 = ret2( "named struct example" ); print "ret2() returned a $s2\n"; printf "Is it a structure? [%d]\n", $s2->is_struct_type; printf "With keys/fields [ %s ]\n", join( ", ", keys(%$s2) ); print " s.x = $$s2{x}\n"; print " s.time = $$s2{time}\n";
which, when run, produces
ret1() returned a Struct_Type Is it a structure? [1] With keys/fields [ x, time ] s.x = struct example s.time = Sun Jan 9 18:51:38 2005 ret2() returned a xTime_Struct Is it a structure? [1] With keys/fields [ x, time ] s.x = named struct example s.time = Sun Jan 9 18:51:38 2005
Using "named" structures
use Inline 'SLang' => <<'EOS'; typedef struct { x, foo } My_Struct; define is_okay(x) { if ( typeof(x) != My_Struct ) { vmessage("You sent me a %S", typeof(x)); return; } vmessage( "My_Struct field x = %S", x.x ); vmessage( "My_Struct field foo = %S", x.foo ); } EOS my $s = My_Struct->new(); $$s{x} = 1; $$s{foo} = "foo foo"; is_okay( $s );
which, when run, produces
My_Struct field x = 1 My_Struct field foo = foo foo