如何使用 nim-lang 中的 ImportDll 在 DotNet Core 中调用字符串函数
How to call string function in DotNet Core with ImportDll in nim-lang
我想在我的 C# 代码中使用 Nim,我使用这个 https://www.euantorano.co.uk/posts/nim-with-c-sharp-net/ 示例没有问题。好吧,我说了,让字符串 proc 工作。
proc HelloNim*(a, b: cint): cstring {.cdecl, exportc, dynlib.} =
return "bob".cstring
然后在 C# 中
using System;
using System.Runtime.InteropServices;
namespace Miasma
{
class Program
{
static void Main(string[] args)
{
string b = ""+HelloNim(1,2);
Console.WriteLine(b);
}
[DllImport("HelloNim.dll")]
public static extern void NimMain();
[DllImport("HelloNim.dll")]
public static extern string HelloNim(int a, int b);
}
}
这没有错误,但也没有打印出任何字符串。乐克斯。出了什么问题?
这里出问题的是 C# 认为它正在取回托管字符串,并试图释放它。但是它得到的字符串不在它的内存块中,因为它是由 Nim DLL 分配的,所以它崩溃了(如果你查看 dotnet 的退出代码,它应该是 139,这意味着 SIGSEGV,至少在 Linux ).为避免这种情况,您可以将过程定义为返回 IntPtr
,然后使用 Marshal.PtrToStringUTF8(returnValue)
将其编组为 C# 字符串 另一件需要注意的事情是,对于字符串(或任何其他在 Nim 中使用 GC 的东西,并初始化全局变量)才能工作,你需要先调用 NimMain()
。结合这个你的代码可以重写为:
using System;
using System.Runtime.InteropServices;
namespace Miasma
{
class Program
{
static void Main(string[] args)
{
NimMain();
IntPtr strPtr = HelloNim(1,2);
var str = Marshal.PtrToStringUTF8(strPtr);
Console.WriteLine(str);
}
[DllImport("HelloNim.dll")]
public static extern void NimMain();
[DllImport("HelloNim.dll")]
public static extern IntPtr HelloNim(int a, int b);
}
}
另外请记住,您收到的指针指向 Nim 管理的内存,因此每次您从 Nim DLL 调用某些内容时,它都有可能被 GC 处理。如果您想将它保留在您的 C# 代码中,您应该立即将其复制过来(不确定 Marshall 是否这样做)。
我想在我的 C# 代码中使用 Nim,我使用这个 https://www.euantorano.co.uk/posts/nim-with-c-sharp-net/ 示例没有问题。好吧,我说了,让字符串 proc 工作。
proc HelloNim*(a, b: cint): cstring {.cdecl, exportc, dynlib.} =
return "bob".cstring
然后在 C# 中
using System;
using System.Runtime.InteropServices;
namespace Miasma
{
class Program
{
static void Main(string[] args)
{
string b = ""+HelloNim(1,2);
Console.WriteLine(b);
}
[DllImport("HelloNim.dll")]
public static extern void NimMain();
[DllImport("HelloNim.dll")]
public static extern string HelloNim(int a, int b);
}
}
这没有错误,但也没有打印出任何字符串。乐克斯。出了什么问题?
这里出问题的是 C# 认为它正在取回托管字符串,并试图释放它。但是它得到的字符串不在它的内存块中,因为它是由 Nim DLL 分配的,所以它崩溃了(如果你查看 dotnet 的退出代码,它应该是 139,这意味着 SIGSEGV,至少在 Linux ).为避免这种情况,您可以将过程定义为返回 IntPtr
,然后使用 Marshal.PtrToStringUTF8(returnValue)
将其编组为 C# 字符串 另一件需要注意的事情是,对于字符串(或任何其他在 Nim 中使用 GC 的东西,并初始化全局变量)才能工作,你需要先调用 NimMain()
。结合这个你的代码可以重写为:
using System;
using System.Runtime.InteropServices;
namespace Miasma
{
class Program
{
static void Main(string[] args)
{
NimMain();
IntPtr strPtr = HelloNim(1,2);
var str = Marshal.PtrToStringUTF8(strPtr);
Console.WriteLine(str);
}
[DllImport("HelloNim.dll")]
public static extern void NimMain();
[DllImport("HelloNim.dll")]
public static extern IntPtr HelloNim(int a, int b);
}
}
另外请记住,您收到的指针指向 Nim 管理的内存,因此每次您从 Nim DLL 调用某些内容时,它都有可能被 GC 处理。如果您想将它保留在您的 C# 代码中,您应该立即将其复制过来(不确定 Marshall 是否这样做)。