Introduction

To begin, PerlSharp was written by Joshua Tauberer and last built was on 6/6/2005...

Compilation

Okay, just extract archive content, I want to compile project: then I remember that nmake is not make !

So I start rewritting a Makefile for nmake, it took me long time to find which compiler to use, how to mix them and which flags to set!

Yes it was my first C# project.

I found nmake file poorer than make for its lake of reading output of a command to define a macro, or I miss something?

So I wrote a pseudo generator in order to setup CC and LD flags from perl Config.pm module here is the *hack* :

!IF EXIST(config.mak)
!ELSE
!MESSAGE Build additional configuration 'config.mak' file
!IF [echo CCFLAGS = \> config.mak]
!ENDIF
#Take ccflags without -MT -MD -MDd -MTd
!IF [perl -MConfig -e "$$_=$$Config{ccflags};s!(-|/)M(T|D)d?!!g; print $$_,' -I',$$Config{archlibexp}.'\CORE'" >> config.mak]
!ENDIF
!IF [echo+  >> config.mak]
!ENDIF
!IF [echo LDFLAGS = \>> config.mak]
!ENDIF
!IF [perl -MConfig -e "print join ' ', $$Config{libperl}, '-libpath:'.$$Config{archlibexp}.'\CORE'" >> config.mak]
!ENDIF
!MESSAGE Configuration file generated.
!ENDIF
!INCLUDE config.mak

C# DllImport referenced to "perl" which is resolved to perl.dll but I was working with perl 5.10 and required them to resolved to perl510.dll.

So I was refactoring all DllImport to they point to a constant into the master namespace, so I can change the reference without editing every sources.

namespace Perl {
  public class PERL_DLL{
    public const String name = "perl510";
  }
...
  [DllImport(PERL_DLL.name)] private static extern IntPtr perl_alloc();
}

Then, it took me time again to fix minor bugs (ref count and initialization specific to Perl under Win32) and functions exports.

But the part that take me the most of the time is the XSUB callback system, a bridge between C# Managed code and Perl XS glue.

It was running an access violation while returning from C# or sometime from XS callbacks I though it was due to a Perl stack corruption, so I decided to rewrite the bridge to make it falling under XS rather than C# which is to new for me; it was working 8-)

Yes, but I was adding lots of Perl_Warn call to trace code, and as soon as I commented out some of them it was generating access violation exceptions randomly :-/

I finally find that C# export it's delegate using stdcall convention by default but my XS glue was expected cdecl convention.

So after removing all hacks arround callbacks, the final fix was just to add an attribute line before the delegate declaration:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void XSUB(IntPtr interpreter, IntPtr args);

To resume, it took me about two days to write one line of code!

Hacking a bit

Now it was working I start to play with it and found that it generate perl.exe (a .net perl interp) which now conflict with my system perl interpreter!

I decided to rename perl.exe as perlinterp.exe, and added a code line just after interpreter initialisation in order to let's perl script manipulate the C# interpreter object itself.

...
  Interpreter perl = new Interpreter();
  perl.AddExtensionObject( perl );
...

I was looking for a way to inject an assembly from perl script and wrote a method Interpreter.Using( namespace ) which try to load the assembly, and an Interpreter.CreateObject( typename ) method that will create a instance of a particular object.

So I could write a perl script (samples/script02.pl) that open a WinForm wich is declared in a separated assembly ( samples/MyForm.dll ).

What's inside ?

>ildasm PerlSharp.dll

ILDASM of PerlSharp.dll 1.0.0.1 for MS.Net

Limitation

The callback system create a XS Bridge for each public method of an object passed to Interpreter.AddExtensionObject.

The trick is that overloaded methods is not handled with this system, as Perl 5 disallow to declare multiple subs with the same name, because argument list is variable by default.

Another limitation is that the package method exported is linked with a particular instance of a C# object.

Conclusion

This was a good C# learning challenge for me ;) but I may consider to write something else if I want to better interact between .Net and Perl 5.

But if you want to hack yourself, the MS.Net release is attached.

License

Still the one fixed by the author: the README file say "PerlSharp is released under the GPL."