【问题标题】:Passing byte array to PInvoke call changes it to null将字节数组传递给 PInvoke 调用将其更改为 null
【发布时间】:2014-02-08 20:09:03
【问题描述】:

从 Visual Studio 2012 迁移到 2013 后,一些 PInvoke 调用无法像以前那样工作。

例如,我正在为这段代码苦苦挣扎:

签名:

 [DllImport(LzoDll64Bit)]
    private static extern int lzo1x_decompress(byte[] src, int src_len, byte[] dst, ref int dst_len, byte[] wrkmem);

用法:

byte[] dst = new byte[origlen];
int outlen = origlen;
if (Is64Bit())
    lzo1x_decompress(src, src.Length - 4, dst, ref outlen, _workMemory);
else
    lzo1x_decompress32(src, src.Length - 4, dst, ref outlen, _workMemory);

预计 lzo1x_decompress(...) 会填充新初始化的 byte[] dst 数组,但在 VS 2013 中奇怪的行为是调用该函数后,dst 数组变为空值而不是被填充。

此外,整个应用程序的状态似乎是稳定的,在此期间没有发生错误。

什么可能导致这种情况或如何避免这种情况甚至调试错误?

【问题讨论】:

  • 这样的问题确实需要界面的两面。你只展示了管理的一面。我用谷歌搜索了非托管方面,但我不能确定我找到了正确的功能。
  • 不幸的是我没有非托管的一面。
  • 所以你只是在猜测那里有什么?

标签: c# .net arrays pinvoke marshalling


【解决方案1】:

您似乎以错误的方式进行此操作。看到您根据代码是 32 位还是 64 位来切换行为,这是一个令人担忧的迹象。这是一个明显的迹象,表明你有问题。我相信非托管声明看起来像这样:

int lzo1x_decompress(const unsigned char *in, size_t in_len,
    unsigned char *out, size_t *out_len, unsigned char *wrkmem);

对于 32 位和 64 位代码,匹配的 p/invoke 声明是:

[DllImport(LzoDll, CallingConvention=CallingConvention.Cdecl)
static extern int lzo1x_decompress(byte[] in, IntPtr in_len, 
    [Out] byte[] out, ref IntPtr out_len, byte[] wrkmem);

您的代码错误地将int 用于两个size_t 参数。现在,size_t 在 Windows 上是指针大小,因此匹配类型是 IntPtr

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-13
    • 2019-02-15
    • 2014-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多