PerlNET: The Camel Talks.NET Jan Dubois JanD@ActiveState.com The Perl Conference 6 San Diego, July...

Preview:

Citation preview

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