Perlembed - C# - Mono - Linux

PerlEmbed - C# - Mono - Linux

Got it to work!

Made the perl program, showtime.pl:

#/usr/bin/perl

sub showtime {
print "WOOT!\n";
}

Made the c program, perlembed.c:

#include <EXTERN.h>
#include <perl.h>

static PerlInterpreter *my_perl;

void Initialize(char* processName, char* perlFile)
{
int argc = 2;
char *argv[] = { processName, perlFile },
*env[] = { "" };

PERL_SYS_INIT3(&argc, &argv, &env);
my_perl = perl_alloc();
perl_construct(my_perl);
perl_parse(my_perl, NULL, argc, argv, NULL);
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
}

void Call(char* subName)
{
char *args[] = { NULL };
call_argv(subName, G_DISCARD | G_NOARGS, args);
}

void Dispose()
{
if (my_perl != NULL)
{
perl_destruct(my_perl);
perl_free(my_perl);
PERL_SYS_TERM();
my_perl = NULL;
}
}

Compiled it via:

"gcc -shared -Wl,-soname,perlembed.so -o perlembed.so perlembed.c `perl -MExtUtils::Embed -e ccopts -e ldopts`"

Made this C# program, perlembed.cs:

using System;
using System.Runtime.InteropServices;

public class Woot
{
[DllImport("perlembed.so", SetLastError = true)]
public static extern void Initialize(string processName, string perlFile);

[DllImport("perlembed.so", SetLastError = true)]
public static extern void Call(string subName);

[DllImport("perlembed.so", SetLastError = true)]
public static extern void Dispose();

static void Main()
{
Console.WriteLine("Starting up C#...");

try
{
Initialize("perlembed.exe", "showtime.pl");

Call("showtime");
}
catch(Exception exc)
{
Console.WriteLine(exc.ToString());
}
finally
{
Dispose();
}

Console.WriteLine("DONE!...");
}
}

Compiled it with gmcs, and got the output:

Starting up C#...
WOOT!
DONE!...

Hope this helps anyone out there, can't believe it took 3 languages to happen. I will move on to passing scalars, arrays, etc. but it should be a breeze from here.

How can I embed a Perl interpreter in my C# program using Mono on Linux?

Interop works fine with Mono under Linux to call C-Code.
Thus I would consider that you look at perlembed.
Instead of a C-program you need to create a shared C-library.
For Interop there are several good guides - a potential pitfall are sizes of datatypes, because you get really plaform/CPU dependent.
Let me know if you need anywhere more detailed information.

Usage of FileInfo and DirectoryInfo classes on Mono - Linux

Technically it should be faster on Linux machines as the file system enumeration is generally faster than Windows.

but We want to assess Mono BCL against custom Mono.Posix, I checked underlying implementation of both assemblies and while both would call system functions at the end, the route is different as the former use Mono runtime abstractions but the latter use direct p/invoke, so I wrote a simple code to assess performance differences for Directory and File enumeration and here it is:

    public static void Main (string[] args)
{
Assess ("/opt",5, false);
Console.WriteLine ("**********************");
Assess ("/opt",5, true);
}

public static void Assess (string root,int iteration, bool net=true)
{
var watch = new Stopwatch ();
var fCount = 0;
var dCount = 0;

watch.Start ();
for (var i=0; i<iteration; i++) {
if (net) {
Console.WriteLine ("assessing .Net Bcl");
var dirInfo = new System.IO.DirectoryInfo (root);
AssessNet (dirInfo, ref fCount, ref dCount);
} else {
Console.WriteLine ("assessing Mono Posix");
var unixDirInfo = new Mono.Unix.UnixDirectoryInfo (root);
AssessMono (unixDirInfo, ref fCount, ref dCount);
}
}
watch.Stop ();
Console.WriteLine ("crawl time: {0} ms", watch.ElapsedMilliseconds);
Console.WriteLine ("files count: {0}, directory count: {1}", fCount, dCount);
}

public static void AssessNet (System.IO.DirectoryInfo root, ref int fCount, ref int dCount)
{
var files = root.GetFiles ();
var dirs = root.GetDirectories ();

foreach (var f in files) {
fCount++;
}

foreach (var d in dirs) {
dCount++;
AssessNet (d, ref fCount, ref dCount);
}
}

public static void AssessMono (Mono.Unix.UnixDirectoryInfo root,ref int fCount,ref int dCount)
{
var entries = root.GetFileSystemEntries ();

foreach (var e in entries) {
if (e.IsDirectory) {
dCount++;
AssessMono (e as Mono.Unix.UnixDirectoryInfo,ref fCount,ref dCount);
} else {
fCount++;`enter code here`
}
}
}
}

I tested with Mono 3.2.8 on Ubuntu 14.04.1 64-bit

Here is the result:

assessing Mono Posix

crawl time: 469 ms,
files count: 16020, directory count: 2965


assessing .Net Bcl

crawl time: 705 ms,
files count: 16020, directory count: 2965

based on my experiment there is a performance difference, so based on your requirement, and considering subtle differences between the two API , it may not be such a bad idea to write a thin wrapper to achieve best results on both Operating Systems
(we can use direct Win32 calls on windows as default implementation of File and Directory IO in .Net is slow too).



Related Topics



Leave a reply



Submit