如何在 C# struct 中声明和使用固定大小的字符缓冲区

Posted

技术标签:

【中文标题】如何在 C# struct 中声明和使用固定大小的字符缓冲区【英文标题】:How to declare and use fixed size char buffer in C# struct 【发布时间】:2016-06-15 05:15:36 【问题描述】:

我有以下结构声明:

[StructLayout(LayoutKind.Sequential)]
public struct MyDLLInput

    ...
    public fixed char PathtoData[256];
;

PathtoData 按原样显示错误:

"Pointers and fixed-size buffers may only be used in an unsafe context."

MyDLLInput 被传递给 C++ DLL:

public class MyDLL

    [DllImport("MyDLL.dll",
        EntryPoint = "?Unit@@YA?AUOutput@@UInput@@@Z",
        CallingConvention = CallingConvention.Cdecl)]
    public static extern MyDLLOutput Unit(MyDLLInput UnitInput);

MyDLL.h 将成员定义为:

char PathtoData[256];

如何在我的 C# 代码中正确地进行成员声明?

【问题讨论】:

你能用成员 PathToData 展示完整的 C++ 类吗?另外为什么不使用Exporting C++ Functions for Use 而不是像 "?Unit@@YA?AUOutput@@UInput@@@Z" 这样的错位函数名称? @ArtavazdBalayan C++ DLL 是由另一位开发人员提供给我的。我没有源代码,虽然我可以得到它。我不太了解 C++,无法按照您的建议进行操作。通过 Dependency Walker 向我提供了损坏的名称。 @ArtavazdBalayan 但我会将您的链接转发给该 C++ DLL 的开发人员。错位的名字并没有真正困扰我。一旦它到位,它就看不见了,但我确实喜欢你的建议。 我为什么要询问 C++ 代码,因为我不确定您在这里需要不安全。这只是 P/Invoke。 【参考方案1】:

正如它所说:

指针和固定大小的缓冲区只能在不安全的上下文中使用。

所以为了像这样使用固定大小的字符缓冲区,您需要将unsafe 添加到您的结构中:

public unsafe struct MyDLLInput

   ...
   public fixed char PathtoData[256];
;

您还需要允许这样的不安全编译:

    右键单击您的项目。 选择“属性”。 切换到“构建”选项卡。 勾选“允许不安全代码”

根据MSDN - Unsafe Code and Pointers (C# Programming Guide)

在公共语言运行时 (CLR) 中,不安全的代码被称为无法验证的代码。 C# 中的不安全代码不一定是危险的;它只是 CLR 无法验证其安全性的代码。因此,如果 CLR 位于完全受信任的程序集中,则 CLR 只会执行不安全的代码。如果您使用不安全的代码,您有责任确保您的代码不会引入安全风险或指针错误。

有关安全和不安全代码的更多信息和比较,您还可以查看 Safe and Unsafe Code 在 MSDN。

【讨论】:

我从未使用过unsafe。您的示例处理了所有错误。对于unsafe 如何影响应用程序的其余部分,是否有一个简单的解释?或者此设置是否只影响标有unsafe 属性的代码? 另请注意,C++ 中的 char 通常是 8 位(取决于平台),但在 C# 中是 16 位(如果在 Windows 上,则在 C++ 中为 wchar_t)。简而言之:将类型更改为字节并处理编码转换。 @rwkiii,我更新了答案,但是您应该考虑编码转换,因为 Adriano 提到的是他的评论。 @hsh 是的,我已将其设置为字节。谢谢你们俩。这一切都非常有帮助。

以上是关于如何在 C# struct 中声明和使用固定大小的字符缓冲区的主要内容,如果未能解决你的问题,请参考以下文章

Unity:列表变量数组。如何在 C# 中正确声明它

C# 关于Struct的思考

为啥 16 字节是 C# 中 struct 的推荐大小?

如何在 C# 中使用 struct 和 union

不同应用程序(WPF 和 Unity)中的 C# struct 序列化返回不同大小的字节数组

TypeScript:如何在编译时声明固定大小的数组以进行类型检查