Post on 18-Jan-2016
PerlNET: The Camel Talks .NET
Jan Dubois
JanD@ActiveState.com
The Perl Conference 6
San Diego, July 26th 2002
Agenda
How does PerlNET work
PerlNET Challenges
Demonstrations
Questions and Answers
.NET Acronyms
CLR – Common Language Runtime
CTS – Common Type System
CLS – Common Language Spec
CIL – Common Intermediate Language
.NET Terms
Managed Code & Data Types implemented in CIL Uses object references Garbage collection
Unmanaged Code & Data Platform native code (e.g. Win32, Kernel) Direct memory access
PerlNET Design Goals
Perl Standard Perl Syntax Full support for XS extension modules Reasonable execution speed
.NET Using .NET objects from Perl Implementing .NET objects in Perl Cross-language inheritance support CLS compliance
PerlNET Component
Perl Host
Perl 5.6.1Module Proxy
Managed Runtime
Module.pm
.NET Framework Windows
.NET Interface
PerlNET Features
Constructors & Inheritance Methods incl. overloading Fields, Properties & Indexers Events (Delegates) Enumerations Exceptions Custom attributes Namespaces P/Invoke
Challenges
Overloading
Data Marshalling
Object Lifetime
Exception Handling
Debugging
Overloading
.NET Statically typed Overloaded constructors & methods
Perl Dynamically typed Runtime parameter inspection
Implementing overloaded methods
package PerlObj;
=for interfacevoid Write(char arg);void Write(short arg);void Write(int arg);void Write(long arg);void Write(double arg);void Write(decimal arg);=cut
sub Write { my($this, $arg) = @_; print $arg;}
package PerlObj;
=for interfacestring Property;private field string data;=cut
sub Property { my($this, $val) = @_; if (defined $val) { $this->{data} = $val; } return $this->{data};}
Called from C#:
obj.Property = "My Value";Console.WriteLine(obj.Property);
use PerlNET qw(AUTOCALL bool); Prints:use namespace "System"; # call Write(System.Int32)my $var = 1;Console->Write($var); => 1
# call Write(System.Double)$var += 1;Console->Write($var); => 2
# call Write(System.Int32)Console->Write(int($var)); => 2
# call Write(System.String)Console->Write("$var"); => 2
# call Write(System.Boolean)Console->Write(bool($var)); => True
Calling overloaded methods
Passing .NET types to Perl
Value types passed as bit patterns Wrapped in a Perl object Can be passed back to .NET as same type Overloaded operators
Reference types are passed as GCHandles Reference counted on the Perl side
Passing Perl variable to .NET
All variables passed as IntPtrs
PerlRT knows Perl variable layout
“Unsafe” managed code accesses Perl variable internals as needed
Data passed back to Perl is not unpacked
Marshalling Strings
System.String constructed directlyfrom Perl scalar value:
Encoding enc = (Flags & sv_flags.UTF8) == 0 ? Encoding.Default : Encoding.UTF8;
byte *xpv = (byte*)*(int*)sv;
return new String((sbyte*)*(int*)xpv, 0, *(int*)(xpv+4), enc);
Object Lifetime
Perl Counts references Calls DESTROY() method immediately Deterministic destruction order
.NET Tracks object references Calls Finalize() method “later” Managed objects destroyed in arbitrary order Cannot access other objects in Finalize()
IDisposable interface
Explicit Dispose() paradigm
PerlObj obj = new PerlObj();try { // Work with obj obj.DoSomething();}finally { if (obj != null) obj.Dispose();}
C# syntactic sugar
using (PerlObj obj = new PerlObj()) { // Work with obj obj.DoSomething();}
PerlNET object lifetime
PerlNET makes sure that DESTROY is called (eventually)
PerlNET objects are not collected by .NET unless they are explicitly disposed or at the end of the program
Exception Handlingclass CSharpObj {
static void Main() { try { PerlObj.bar(new CSharpObj()); } catch (Exception e) { Console.WriteLine(e); }}
void foo() { Console.WriteLine("inside foo"); throw new ApplicationException();}}
package PerlObj;
=for interfacestatic void bar(any obj);=cut
sub bar { my $obj = shift; print "inside bar\n";
eval { $obj->foo() }; print "$@\n" if $@;
$obj->foo(); print "not reached\n";}
inside foo
inside bar
inside foo
System.ApplicationException: Error in the application. at CSharpObj.foo()
System.ApplicationException: Error in the application. at PerlObj.bar(Object obj) at CSharpObj.Main()
Debugging
Perl debugger partially written in Perl
Breakpoints freeze all managed threads
Workaround: run Perl in separate thread(uses different call stack)
“Step out” doesn’t work(need to set breakpoint manually)
Wrapping a CPAN Module
Install CPAN module
Create interface specification
Compile into .NET assembly
Use from C# program
Windows Forms Sample
Create simple Form
Add Textbox and Button
Implement delegate for Click event
Cross-Language Inheritance
Design GUI using Visual C#
Add data members and virtual callbacks
Implement callbacks in Perl
ASP.NET
Active Server Pages .NET HTML + Source code Inherits System.Web.UI.Page behavior Compiles into .NET assembly Cached by IIS / ASP.NET
Perl for ASP.NET CodeGenerator translates CodeDOM PerlNET creates .NET component
Web Services
Based on ASP.NET CodeGenerator
Just add [WebMethod] custom attribute
ASP.NET provides Interactive interface for testing WSDL description
Summary
PerlNET is part of the Perl Dev Kit
Migrating Perl applications to .NET
Reusing CPAN modules from other languages
Native compiler to CIL for Perl 6?
Questions & Answers
http://www.ActiveState.com/PDK
mailto:JanD@ActiveState.com