如何从.NETC#程序在Linux下调用本机C或汇编代码?

问题描述

dotnet运行错误定义为here。我正在尝试使用.Net核心x64 Linux在C#中通过C库DllImport运行汇编代码。如何正确执行此操作?

C#:

    using System.Runtime.InteropServices;
class Program{
[DllImport("lib.so")] public static extern int foo ();
 static void Main(string[] args)
        {
            int code = foo();
System.Console.WriteLine(code);
}
}

C my.c

    #define EXPORT __attribute__((visibility("default")))
EXPORT int foo(void);
int foo(void)
{
    extern int _start();
    return _start();
}

程序集asm.s

.text
   .globl _start

   _start:               
   mov $1,%rax
   ret

程序的目标是通过C库从汇编中返回零结果代码。将显示以下错误消息;没有异常:

Hosting components are already initialized.
Re-initialization to execute an app is not allowed.

我已经使用GCC编译了C和Assembly源代码

gcc -shared -fpic -o lib.so my.c asm.s

解决方法

Re-initialization to execute an app is not allowed.

我不确定这里发生了什么,我只有一个怀疑

gcc -shared -o lib.so my.o

使用此命令行生成一个名为lib.so的文件,其中包含文件my.c。但是不是文件asm.s

这意味着该文件不包含符号_start

现在的问题是:在下面的代码行中会发生什么:

return _start();

也许代码会跳到应用程序的_start符号(正在运行C#程序)。

这就像重新启动该应用程序,而无需将全局变量重新设置为初始值并且没有有效的堆栈框架...

编辑

在共享库“ lib.so”中找不到名为“ foo”的入口点。在Program.foo()

问题在于,在C ++,C#或Java的“方法”中使用或在C或C ++的“函数”中使用“ static”关键字时,含义完全不同:

在函数或全局变量中,关键字“ static”表示只能在同一文件内部使用该函数或变量。

(非常类似于C#中的“ private”。)

您必须在C程序中删除“ static”,但必须在C#程序中保留“ static”。

编辑2

我不确定您是否知道从.NET(或从C的汇编)代码调用C的工作方式:

汇编程序就像.NET程序的一部分一样被执行。如果在syscall设置为rax231)的情况下调用exit_group,则汇编函数的行为类似于.NET函数,调用Environment.Exit()

您的C#程序立即停止。因此,code=foo()将不会返回任何值,因为foo()将终止您的C#程序。

要从汇编函数返回值,只需将要返回的值写入rax寄存器。然后用ret指令完成该功能:

_start:
    mov $1,%rax
    ret

不幸的是,这似乎不是异常的原因,因此程序中还有另一个问题...