问题描述
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
设置为rax
(231
)的情况下调用exit_group
,则汇编函数的行为类似于.NET函数,调用Environment.Exit()
:
您的C#程序立即停止。因此,code=foo()
将不会返回任何值,因为foo()
将终止您的C#程序。
要从汇编函数返回值,只需将要返回的值写入rax
寄存器。然后用ret
指令完成该功能:
_start:
mov $1,%rax
ret
不幸的是,这似乎不是异常的原因,因此程序中还有另一个问题...