如何使用 *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
(没有 ref
或 out
)。
此外,请确保使用正确的编组属性。 .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/
我有这个本机界面:
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
(没有 ref
或 out
)。
此外,请确保使用正确的编组属性。 .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/