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
Parameters Passed by Reference Come Back Garbage Using P/Invoke
Casting Interfaces for Deserialization in JSON.Net
Is There a Way of Setting Culture for a Whole Application? All Current Threads and New Threads
C# - Multiple Generic Types in One List
Compiler Ambiguous Invocation Error - Anonymous Method and Method Group with Func<> or Action
How to Use a C# Keyword as a Property Name
Stataskscheduler and Sta Thread Message Pumping
How to Find the Most Recent File in a Directory Using .Net, and Without Looping
How to Put Delay Before Doing an Operation in Wpf
How to Autheticate to Ibm Mq C# with Tls-Certificate
System.Missingmethodexception: Method Not Found
How to Merge Multiple Assemblies into One
Async/Await With/Without Awaiting (Fire and Forget)