如何使用 *char 数据 link 到 C# class 的本机 DLL

How to link native DLL to C# class with *char data

我有这个本机界面:

void CLASS_Version(char *Version);

我尝试导入它:

[DllImport("class.dll", EntryPoint = "CLASS")]
private static extern void CLASS_Version(ref string[] Version);

[DllImport("class.dll", EntryPoint = "CLASS")]
private static extern void CLASS_Version(ref char[] Version);

[DllImport("class.dll", EntryPoint = "CLASS")]
private static extern void CLASS_Version(out string[] Version);

[DllImport("class.dll", EntryPoint = "CLASS")]
private static extern void CLASS_Version(out char[] Version);

但我总是得到 "AccessViolation" 错误, 唯一好的运行是用

制作的
[DllImport("class.dll", EntryPoint = "CLASS")]
private static extern void CLASS_Version(ref char Version);

但是这样我只得到了字符串的第一个字符...如何得到所有的字符串?

char * 有歧义,但绝对不是字符串数组。它很可能是一个指向字符串的指针,因此您将只使用一个简单的 StringBuilder(没有 refout)。

此外,请确保使用正确的编组属性。 .NET 字符串始终是宽字符,与您的签名不同。

一般来说,函数的签名不足以与本机代码进行适当的互操作。您需要了解参数和 return 值的含义,并且需要了解调用约定。您需要阅读文档,换句话说:)

基本上指针是用IntPtr类型表示的。
另外,入口点应该是表示函数名称的字符串

尝试:

[DllImport("class.dll", EntryPoint = "CLASS_Version")]
private static extern void CLASS_Version(IntPtr Version);

试试这个:

[DllImport("class.dll", EntryPoint = "CLASS")]
private static extern void CLASS_Version([MarshalAs(UnmanagedType.VBByRefStr)] ref string Version); 

当你要调用你的方法时:

Version = Space(14);// first declare memory space requiered ¿14 bytes? ¿more?
CLASS_Version(Version);

遗憾的是,答案不能仅由类型决定。 如果有那么简单,就会有解析器可以为您编写本机包装器。 您必须使用的类型取决于函数实际执行的操作。

在您的情况下,char * 未标记为 const,它被接受为参数,这意味着它旨在成为用户分配的可用于该函数的内存区域写给。由于没有大小参数,很可能存在版本字符串的最大大小,应该在代码文档中指明。

鉴于这是字符串处理,您还需要担心编码问题。为了简单起见,我假设(并希望)您的字符串是 ASCII/Windows-1252 而不是 UTF8、UTF7 或其他格式。

鉴于这些假设,您有多种选择,但我将根据所提供的信息仅介绍处理此问题的首选方法。 (可能您的情况需要不同的东西,但这是我根据从您问题中的信息推断出的假设提出的最佳解决方案。)

[DllImport("class.dll", EntryPoint = "CLASS_Version", , CharSet = CharSet.Ansi)] // CharSet is important
private static extern void CLASS_Version(StringBuilder Version);

这是处理这种情况的 'correct' 方法 - 依靠编译器为您处理编组。但是,有一点需要注意,您必须在将 StringBuilder 传递给该方法之前手动设置它的容量。

// be sure to allocate a correct size,
// there will be no error if it overflows because it's too small
StringBuilder buffer = new StringBuilder(size); 
// automagically marshalled to and from unmanaged code byt the compiler
CLASS_Version(buffer);
string version = buffer.ToString();

我想借此机会指出 CLASS_Version 不应该是 private。您所有的本机方法都应该 public 并组合在一个 internal static class.

您可能会发现一些关于字符串编组的额外资源: https://limbioliong.wordpress.com/2011/11/01/using-the-stringbuilder-in-unmanaged-api-calls/