如何使用* char数据将本机DLL链接到C#类

时间:2016-03-16 13:41:20

标签: c# native dllimport

我有这个原生界面:

[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);

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

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

制作的
org.glassfish.jersey.server.ResourceConfig

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

4 个答案:

答案 0 :(得分:4)

char *含糊不清,但绝对不是字符串数组。最有可能的是,它是指向字符串的指针,因此您只需使用简单的StringBuilder(无refout)。

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

通常,函数的签名不足以与本机代码正确互操作。您需要了解参数和返回值的含义,并且您需要知道调用约定。您需要阅读文档,换句话说:)

答案 1 :(得分:0)

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

尝试:

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

答案 2 :(得分:0)

试试这个:

[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);

答案 3 :(得分:0)

可悲的是,答案不能仅靠类型来确定。 如果它很简单就会有解析器可以为你编写本机包装器。 您必须使用的类型取决于函数实际执行的操作。

在您的情况下,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);

这是正确的'管理情况的方法 - 依靠编译器为您处理编组。但有一点需要注意的是,在将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/