通过 PInvoke 将 byte[] 作为 IntPtr 传递给 memset

Posted

技术标签:

【中文标题】通过 PInvoke 将 byte[] 作为 IntPtr 传递给 memset【英文标题】:Passing byte[] as IntPtr by PInvoke to memset 【发布时间】:2015-10-24 21:42:57 【问题描述】:

我需要将一个字节数组传递给 memset,由于 P/Invoke 笨拙而需要 IntPtr。手工测试,它有效,但我正在寻求理论上的确认。这个方法对吗?

[DllImport("msvcrt.dll", EntryPoint = "memset", CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
public static extern IntPtr MemSet(IntPtr dest, int c, int count);

static unsafe void ZeroMemset (byte[] data)

    fixed (byte* bytes = data) 
        MemSet ((IntPtr)bytes, 0, data.Length);
    

【问题讨论】:

没有“矮胖”。您的错误是没有以合乎逻辑的方式声明 dest 参数。应该是byte[]。通过以正常方式声明第二个参数byte 来删除额外的块状。不笨重的 pinvoke marshaller 会处理其他所有事情。 我的意思是笨拙,一个错误。对不起。 @Hans 第二个参数是int:void *memset( void *dest, int c, size_t count ); 不,只使用 int 的低字节。 pinvoke marshaller 不需要帮助将字节提升为 int。 @Hans 我以为你在暗示 int 是错误的 【参考方案1】:

您的代码很好,可以正常工作。

在我看来,避免unsafe 并将memset 的参数声明为byte[] 是完全合理的,而且更清楚。我会这样声明:

[DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr memset(byte[] dest, int c, IntPtr count);

请注意,最后一个参数是指针大小的size_t

我也想知道您为什么选择在非托管代码中执行此操作,但大概您有自己的理由。

【讨论】:

PInvoke 签名来自 pinvoke.net。我正在测试不同方法的性能,原生 memset 就是其中之一。 为方便起见,您可以使用byte[] 声明它。我看不出有什么改善。

以上是关于通过 PInvoke 将 byte[] 作为 IntPtr 传递给 memset的主要内容,如果未能解决你的问题,请参考以下文章

PowerEnumerate PInvoke 调整数组大小

如何使用 pinvoke 将二进制数据缓冲区从 C 传递到 C#

在 c# 和 c++ 之间将 double 类型的二维多维数组作为输入和输出的 pinvoke 编组

PInvoke 与指针 - C++ 到 C#

使用协议缓冲区/Protobuf 的 PInvoke 通用字符串格式

C DLL 中的 PInvoke char* 在 C# 中作为字符串处理。空字符问题