diff --git a/Makefile b/Makefile index 3e49d71d..1cd3a3ca 100644 --- a/Makefile +++ b/Makefile @@ -55,7 +55,12 @@ obj/Kernel.dll: $(patsubst %,lib/%,$(cskernel)) lib/unidata $(CSC) /target:exe /out:obj/Kernel.dll /lib:obj /unsafe+ \ /res:lib/unidata $(patsubst %,lib/%,$(cskernel)) -perl5: obj/Perl5Interpreter.dll obj/p5embed.so + +.PHONY: Niecza_pm +perl5: obj/Perl5Interpreter.dll obj/p5embed.so Niecza_pm +Niecza_pm: + cd perl5/Niecza;perl Build.PL;perl Build + obj/Perl5Interpreter.dll: obj/Run.Kernel.dll lib/Perl5Interpreter.cs $(CSC) /target:library /lib:obj /out:obj/Perl5Interpreter.dll /r:Run.Kernel.dll lib/Perl5Interpreter.cs diff --git a/lib/Perl5Interpreter.cs b/lib/Perl5Interpreter.cs index 3186198f..12f0f60b 100644 --- a/lib/Perl5Interpreter.cs +++ b/lib/Perl5Interpreter.cs @@ -2,6 +2,7 @@ using System.Runtime.InteropServices; using System; using System.IO; +using System.Collections.Generic; using Niecza.Serialization; public class Perl5Interpreter : IForeignInterpreter { @@ -41,6 +42,12 @@ public class Perl5Interpreter : IForeignInterpreter { [DllImport("p5embed", EntryPoint="p5embed_SvOK")] public static extern int SvOK(IntPtr sv); + [DllImport("p5embed", EntryPoint="p5embed_SvRV")] + public static extern IntPtr SvRV(IntPtr sv); + + [DllImport("p5embed", EntryPoint="p5embed_sv_isa")] + public static extern int sv_isa(IntPtr sv,string name); + [DllImport("p5embed", EntryPoint="p5embed_newSVpvn")] public static extern IntPtr newSVpvn(IntPtr s,int length); @@ -54,6 +61,13 @@ public static extern IntPtr SubCall( int argument_n ); + + public delegate int create_LoS_delegate(int len,IntPtr data); + + [DllImport("p5embed", EntryPoint="p5embed_set_create_LoS")] + public static extern void Set_p5embed_create_LoS(create_LoS_delegate f); + + // We can't use the standard char* conversion because some strings can contain nulls public static string UnmarshalString(IntPtr sv) { int len = SvPVutf8_length(sv); @@ -63,6 +77,9 @@ public static string UnmarshalString(IntPtr sv) { return System.Text.Encoding.UTF8.GetString(target); } + static Dictionary ExportedObjects; + static int ExportedID; + public static Variable SVToVariable(IntPtr sv) { if (sv == IntPtr.Zero) { //TODO: check - cargo culted @@ -79,12 +96,16 @@ public static Variable SVToVariable(IntPtr sv) { } else if (SvPOKp(sv) != 0) { string s = UnmarshalString(sv); //SvPV_nolen(sv); return Kernel.BoxAnyMO(s, Kernel.StrMO); + } else if (sv_isa(sv,"Niecza::Object") != 0) { + return ExportedObjects[SvIV(SvRV(sv))]; } else { return new SVVariable(sv); } } public Perl5Interpreter() { + ExportedObjects = new Dictionary(); + ExportedID = 8; string location = System.Reflection.Assembly.GetExecutingAssembly().Location; string[] paths = new string[] {"perl5/Niecza/blib/lib","perl5/Niecza/blib/arch"}; @@ -97,6 +118,18 @@ public Perl5Interpreter() { } paths[i] = p5lib; } + Set_p5embed_create_LoS(delegate(int len,IntPtr data) { + int id = ExportedID++; + IntPtr[] target = new IntPtr[len]; + Marshal.Copy(data, target, 0, len); + + string[] args = new string[len]; + for (int i=0;i,q:to/PERL5/); +use Data::Dumper; +my $LoS = Niecza::create_LoS(["foo1","bar1","baz1"]); +$LoS; +PERL5 +is $LoS[0],"foo1"; +is $LoS[1],"bar1"; +is $LoS[2],"baz1"; +done;