Win32::CLR - Use .NET Framework facilities in Perl
use Win32::CLR; use utf8; # binmode STDOUT, ":encoding(Shift_JIS)"; # japanese character set # creating instance my $dt1 = Win32::CLR->create_instance("System.DateTime", 2007, 8, 9, 10, 11, 12); # getting property print $dt1->get_property("Year"), "\n"; # 2007 # calling method my $dt2 = $dt1->call_method("AddYears", 3); print $dt2->get_property("Year"), "\n"; # 2010 my $asm = "System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; # loading assembly by name Win32::CLR->load($asm); # after loading assembly, System.Windows.Forms.* classes can be used Win32::CLR->call_method( "System.Windows.Forms.MessageBox", # type "Show", # method "Message", # parameter "Title" # parameter ); # creating generic instance my $generic = "System.Collections.Generic.Dictionary<System.String, System.Int32>"; my $dict = Win32::CLR->create_instance($generic); $dict->set_property("Item", "ABC", 4321); # dict["ABC"] = 4321; print $dict->get_property("Item", "ABC"), "\n"; # 4321
Win32::CLR provides utility methods to using Microsoft .NET Framework, also known as Common Language Runtime. It is available for creating object, calling method, accessing field or property, converting perl subroutine to delegate, loading assembly.
Creates .NET Framework object of TYPE. The constructor that matches @PARAMS is used.
my $dt = Win32::CLR->create_instance( "System.DateTime", 2007, 8, 9, 10, 11, 12 );
Calls the static method declared in TYPE. @PARAMS must be primitive value or Win32::CLR instance. If @PARAMS contain array reference, it is converted to System.Array.
# in .net # static void MyType::Foo(String^ param); # in perl Win32::CLR->call_method("MyType", "Foo", "foo"); # static void MyType::Foo2(String^ param1, Int32 param2); Win32::CLR->call_method("MyType", "Foo2", "foo", 4321); # static void MyType::Foo3(array<Object^>^ params); Win32::CLR->call_method("MyType", "Foo3", ["foo", "bar", ...]);
Returns the static field declared in TYPE. If field has index, optional parameter $INDEX can be used.
# in .net # field = MyType::Foo; Win32::CLR->get_field("MyType", "Foo"); # MyType::Foo[0] Win32::CLR->get_field("MyType", "Foo", 0);
Sets $PARAM in the static field declared in TYPE. $PARAM must be primitive value or Win32::CLR instance. If field has index, optional parameter $INDEX can be used.
Same as get_field, returns the static property declared in TYPE. Optionally, $INDEX can be used.
# in .net # dict["ABC"] $dict->get_property("Item", "ABC");
Same as set_field, sets $PARAM in the static property declared in TYPE. Optionally, $INDEX can be used.
# in .net # dict["ABC"] = 4321; $dict->set_property("Item", "ABC", 4321);
If property exists in TYPE, calls get_property, or otherwise calls get_field.
Same as get_value, sets $PARAM in static property or field.
Sets event handler in the static event declared in TYPE. $DELEG must be System.Delegate or subroutine reference.
my $deleg = Win32::CLR->create_delegate( "System.EventHandler", sub {print "do something"}, ); $button->add_event("Click", $deleg); $button->remove_event("Click", $deleg); # directly, but addition only! $button->add_event("Click", sub {print "do something"});
Removes event handler $DELEG from TYPE. $DELEG must be System.Delegate.
Creates System.Delegate from perl subroutine. $CODE can contain "sub_name" or \&sub_ref. TYPE is delegate type (ex. System.EventHandler).
my $deleg = Win32::CLR->create_delegate( "System.EventHandler", sub { my ($obj, $event_args) = @_; # do something ... } );
Creates TYPE of System.Array. @PARAMS is setted.
my $array = Win32::CLR->create_array("System.String", "A", "B", "C"); $array->call_method("GetValue", 0); # A $array->call_method("GetValue", 1); # B $array->call_method("GetValue", 2); # C
Creates System.Enum value. TYPE is enum type, VALUES contain list of named constants delimited by commas.
my $binding_flags = Win32::CLR->create_enum( "System.Reflection.BindingFlags", "InvokeMethod, NonPublic" );
Loads assembly by AssemblyQualifiedName. If assembly loaded once, it comes to be able to use the type in assembly. Loaded assembly is cached in memory, so reloading assembly is not required. NAME must be long form of the assembly name. It returns loaded System.Reflection.Assembly object.
my $name = "System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; # $asm can be ignored my $asm = Win32::CLR->load($name); my $button = Win32::CLR->create_instance("System.Windows.Forms.Button");
Loads assembly from file. PATH is path to assembly file. It returns loaded System.Reflection.Assembly object.
Checks TYPE has member NAME. $MEMBER_TYPE is System.Reflection.MemberTypes constants delimited by commas. Default is Method, Field, Property, Event.
if ( Win32::CLR->has_member("System.String", "Length", "Field, Property") ) { print "System.String has Length\n"; }
Returns type name in CLR.
Returns full qualified type name in CLR.
Win32::CLR instance has similar methods to class methods.
$obj->call_method("NAME", @PARAMS) $obj->get_field("NAME", [$INDEX]) $obj->set_field("NAME", [$INDEX, ] $PARAM) $obj->get_property("NAME", [$INDEX]) $obj->set_property("NAME", [$INDEX, ] $PARAM) $obj->get_value("NAME", [$INDEX]) $obj->set_value("NAME", [$INDEX, ] $PARAM) $obj->add_event("NAME", $DELEG) $obj->remove_event("NAME", $DELEG) $obj->has_member("NAME", [$MEMBER_TYPE]) $obj->get_type_name() $obj->get_qualified_type()
Returns object address. Can be used for Inside-out class.
Like UNIVERSAL::isa, returns $obj is derived from TYPE.
Converts $obj to perl primitive string.
If you want to create generic instance, use optional parameter type enclosed by "<>".
my $name = "System.Collections.Generic.Dictionary<System.String, System.Int32>"; my $dict = Win32::CLR->create_instance($name);
Also System.Type.GetType form can be used.
my $name = "System.Collections.Generic.Dictionary`2[System.String, System.Int32]"; my $dict = Win32::CLR->create_instance($name);
"Generic< Generic<Type1, Type2>, Type3 >" # recursive "Generic< Generic`2[Type1, Type2], Type3 >" # mixing my $type = <<"TYPE"; # assembly qualified form System.Collections.Generic.Dictionary< [ System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ], System.Int32 >, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 TYPE # creating generic delegate my $deleg = Win32::CLR->create_delegate( "System.Action<System.String>", sub { print $_[0] } );
Like creating generic type, generic method can be used.
$obj->call_method("method<System.String>", @params);
Win32::CLR automatically converts primitive value between .net and perl.
.net -> perl Boolean -> perl bool SByte, Int16, Int32, Int64 -> perl int Byte, UInt16, UInt32, UInt64 -> perl unsigned int Single, Double -> perl double Char, String, Decimal -> perl string(utf8 flag on) null(nullptr) -> perl undef other -> perl Win32::CLR instance perl -> .net Win32::CLR instance -> Object perl int -> Int32 -> cast target perl unsigned int -> UInt32 -> cast target perl string -> Char, String, Decimal perl double -> Double -> cast target perl undef -> null(nullptr)
When error occurred, System.Exception object is setted in $@. If you want to catch the exception, use eval-block statement. Note that exception message is utf8 encoded.
use Win32::CLR; binmode STDERR, ":encoding(sjis)"; # if japanese windows eval { # Invalid arguments! my $dt1 = Win32::CLR->create_instance("System.DateTime", 2007, 8, 9, 10); }; print STDERR $@->get_property("Message"), "\n"; print STDERR $@->get_type_name(), "\n"; # System.MissingMethodException
Following operators are overloaded.
"" bool == != + - * / % > >= < <= ++ -- my $dt1 = Win32::CLR->create_instance("System.DateTime", 2007, 8, 9, 10, 11, 12); my $dt2 = Win32::CLR->create_instance("System.DateTime", 2008, 8, 9, 10, 11, 12); print "$dt1"; $dt1 == $dt1; $dt1 != $dt2; $dt > $dt2; $dt < $dt2;
If you want compare instance equality, use get_addr method.
$dt->get_addr() == $dt->get_addr()
When calling method named /^(get|set)_\w+/, it is converted to get_value or set_value. If not /^(get|set)_/, converted to call_method. Underscore is ignored and name is ignorecase.
$obj->get_year() -> $obj->get_value("Year") $obj->get_y_e_Ar() -> $obj->get_value("Year") $obj->set_year(1) -> $obj->set_value("Year", 1) $obj->add_years(2) -> $obj->call_method("AddYears", 2) $obj->AddYears(2) -> $obj->call_method("AddYears", 2) $obj->aDd__yEaRs(2) -> $obj->call_method("AddYears", 2)
More tests and documents are required.
Copyright (C) 2008 Toshiyuki Yamato, all rights reserved.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
To install Win32::CLR, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Win32::CLR
CPAN shell
perl -MCPAN -e shell install Win32::CLR
For more information on module installation, please visit the detailed CPAN module installation guide.