将固定大小的缓冲区从 C# 编组到外部
Marshalling a fixed-size buffer from C# to extern
我在使用结构调用某些 Windows kernel32 函数时遇到了一些困难。我正在尝试调用函数 FindFirstStreamW, which return, among others, a WIN32_FIND_STREAM_DATA struct.
我在 C# 中使用这个结构来表示它:
[StructLayout(LayoutKind.Sequential)]
public unsafe struct WIN32_FIND_STREAM_DATA
{
public long StreamSize;
public fixed char StreamName [MAX_PATH + 32];
}
但之后我在使用 StreamName 时遇到了问题。调用该函数后,StreamName 缓冲区似乎包含一个分号(这是预期的),然后只有随机数据。
我尝试用连续的字符替换固定缓冲区,例如 s1、s2、s3 等...并且成功了(s1 包含“:”,然后 s2 包含“$”等...全部正确!)。
[StructLayout(LayoutKind.Sequential)]
public unsafe struct WIN32_FIND_STREAM_DATA
{
public long StreamSize;
public char s1;
public char s2;
public char s3;
}
因此我必须错过一些东西但找不到什么,在 8 个 firefox windows 充满 google 研究之后,我非常绝望。
这是我的 DLLImport:
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr FindFirstStreamW(
[MarshalAs(UnmanagedType.LPTStr)] string filename,
StreamInfoLevels infoLevel,
out WIN32_FIND_STREAM_DATA data,
int reserved = 0
);
还有我的测试代码:
WIN32_FIND_STREAM_DATA data = default(WIN32_FIND_STREAM_DATA);
IntPtr search = FindFirstStreamW(D_TMP_TESTHANDLE_TXT, StreamInfoLevels.FindStreamInfoStandard, out data);
Debug.WriteLine(data.StreamSize);
Debug.WriteLine(new string(data.StreamName));
FindClose(search);
在此先感谢您的帮助。
你的结构的问题 - 与你实际上有不同字符的变体相比 - 可能是它没有按预期进行编组,因为在使用 .NET 时数组是按引用而不是按值默认的。
阅读 this MSDN article 关于字符串编组的更多信息。
所以我会用这样的东西来尝试:
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct WIN32_FIND_STREAM_DATA
{
public long StreamSize;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_PATH+36)]
public string StreamName;
}
我在使用结构调用某些 Windows kernel32 函数时遇到了一些困难。我正在尝试调用函数 FindFirstStreamW, which return, among others, a WIN32_FIND_STREAM_DATA struct.
我在 C# 中使用这个结构来表示它:
[StructLayout(LayoutKind.Sequential)]
public unsafe struct WIN32_FIND_STREAM_DATA
{
public long StreamSize;
public fixed char StreamName [MAX_PATH + 32];
}
但之后我在使用 StreamName 时遇到了问题。调用该函数后,StreamName 缓冲区似乎包含一个分号(这是预期的),然后只有随机数据。
我尝试用连续的字符替换固定缓冲区,例如 s1、s2、s3 等...并且成功了(s1 包含“:”,然后 s2 包含“$”等...全部正确!)。
[StructLayout(LayoutKind.Sequential)]
public unsafe struct WIN32_FIND_STREAM_DATA
{
public long StreamSize;
public char s1;
public char s2;
public char s3;
}
因此我必须错过一些东西但找不到什么,在 8 个 firefox windows 充满 google 研究之后,我非常绝望。
这是我的 DLLImport:
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr FindFirstStreamW(
[MarshalAs(UnmanagedType.LPTStr)] string filename,
StreamInfoLevels infoLevel,
out WIN32_FIND_STREAM_DATA data,
int reserved = 0
);
还有我的测试代码:
WIN32_FIND_STREAM_DATA data = default(WIN32_FIND_STREAM_DATA);
IntPtr search = FindFirstStreamW(D_TMP_TESTHANDLE_TXT, StreamInfoLevels.FindStreamInfoStandard, out data);
Debug.WriteLine(data.StreamSize);
Debug.WriteLine(new string(data.StreamName));
FindClose(search);
在此先感谢您的帮助。
你的结构的问题 - 与你实际上有不同字符的变体相比 - 可能是它没有按预期进行编组,因为在使用 .NET 时数组是按引用而不是按值默认的。
阅读 this MSDN article 关于字符串编组的更多信息。
所以我会用这样的东西来尝试:
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct WIN32_FIND_STREAM_DATA
{
public long StreamSize;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_PATH+36)]
public string StreamName;
}