PerlEmbed – C# – Mono – Linux

前端之家收集整理的这篇文章主要介绍了PerlEmbed – C# – Mono – Linux前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
有没有人试图在 Linux上使用Mono for Monombed?

这是链接perlembed

这是我第一次尝试DllImport签名:

private const string PERL_LIB = "/usr/lib/perl5/5.8.8/i386-linux-thread-multi/CORE/libperl.so";

[DllImport(PERL_LIB,EntryPoint = "perl_alloc",SetLastError = true)]
public static extern IntPtr Alloc();

[DllImport(PERL_LIB,EntryPoint = "perl_construct",SetLastError = true)]
public static extern void Construct(IntPtr hPerl);

[DllImport(PERL_LIB,EntryPoint = "perl_destruct",SetLastError = true)]
public static extern void Destruct(IntPtr hPerl);

[DllImport(PERL_LIB,EntryPoint = "perl_free",SetLastError = true)]
public static extern void Free(IntPtr hPerl);

[DllImport(PERL_LIB,EntryPoint = "perl_parse",SetLastError = true)]
public static extern void Parse(IntPtr hPerl,IntPtr @null,int argc,StringBuilder argv,StringBuilder env);

[DllImport(PERL_LIB,EntryPoint = "perl_run",SetLastError = true)]
public static extern void Run(IntPtr hPerl);

[DllImport(PERL_LIB,EntryPoint = "eval_pv",SetLastError = true)]
public static extern void Eval(string expr,bool flag);

CORE目录可以根据Linux发行版进行更改.

运行以下代码,但在Parse()方法上崩溃:

try
{
    Console.WriteLine("Alloc");
    IntPtr perl = Alloc();

    Console.WriteLine("Construct");
    Construct(perl);

    Console.WriteLine("Parse");
    Parse(perl,IntPtr.Zero,3,new StringBuilder("-e 0"),new StringBuilder());

    Console.WriteLine("Run");
    Run(perl);

    Console.WriteLine("Eval");
    Eval("$a = 3.14; $a **= 2",true);

    Console.WriteLine("Destruct");
    Destruct(perl);

    Console.WriteLine("Free");
    Free(perl);
} 
catch (Exception exc)
{
    Console.WriteLine(exc.ToString());
}

我的崩溃写道:

=================================================================
Got a SIGSEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries
used by your application.
=================================================================

Stacktrace:

in (wrapper managed-to-native) Woot:Parse (intptr,intptr,int,System.Text.StringBuilder,System.Text.StringBuilder) <0x4>
in (wrapper managed-to-native) Woot:Parse (intptr,System.Text.StringBuilder) <0xffff9f85>
in Woot:Main () <0x8d>
in (wrapper runtime-invoke) System.Object:runtime_invoke_void (object,intptr) <0x7c79b09>

本机堆栈跟踪:

mono(mono_handle_native_sigsegv+0xbb) [0x81368fb]
 mono [0x8105670]
 [0x4c45a440]
 /usr/lib/perl5/5.8.8/i386-linux-thread-multi/CORE/libperl.so(perl_parse+0xa3)    [0x4c6e6e93]
 [0x43ad78]
 [0x434cae]
 [0x434abe]
 mono(mono_runtime_exec_main+0x62) [0x80ae5a2]
 mono(mono_runtime_run_main+0x152) [0x80af6e2]
 mono(mono_main+0xef9) [0x805dae9]
 mono [0x805c702]
 /lib/libc.so.6(__libc_start_main+0xdc) [0x4c48d724]
 mono [0x805c651]

perlembed提到了一些PERL_SYS_INIT3和PERL_SYS_TERM调用,但是我无法通过DllImport调用这些方法.在这些情况下我总是得到EntryPointNotFoundException.我确定它们在我需要导入的不同文件中.

有人可以用正确的方式指导我调用DllImports perlembed吗?

解决方法

搞定了!

制作了perl程序,showtime.pl:

#/usr/bin/perl

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

制作了c程序,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;
    }
}

通过以下方式编译:

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

制作了这个C#程序,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!...");
    }
}

用gmcs编译它,得到输出

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

希望这可以帮助那里的任何人,不能相信它需要3种语言才能实现.我将继续传递标量,数组等,但这应该是一件轻而易举的事.

原文链接:https://www.f2er.com/csharp/239054.html

猜你在找的C#相关文章