【发布时间】:2021-04-17 02:59:35
【问题描述】:
我正在为从 C#/.NET 到非托管 DLL 的互操作做一些手动封送处理。
考虑以下结构:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct LockInfo
{
ushort lockVersion;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string lockName;
}
我将其编组到非托管内存:
var lockInfo = new LockInfo();
var lockInfoPtr = Marshal.AllocHGlobal(Marshal.SizeOf(lockInfo));
Marshal.StructureToPtr(lockInfo, lockInfoPtr, false);
完成后,是否需要在lockInfoPtr 上致电Marshal.DestroyStructure?
我知道需要致电Marshal.FreeHGlobal,但在此之前,在这种情况下是否真的需要Marshal.DestroyStructure?
我发现很难理解微软的documentation 围绕这个问题。 Google 搜索没有帮助,可能是因为我还不太了解编组(但我正在学习)。
类似问题...
我已经查看了类似的问题“Marshal.DestroyStructure vs Marshal.FreeHGlobal in .Net”,但是这个问题没有解决 content 结构应该包含的问题,该结构需要使用 DestroyStructure。我有限的理解是 DestroyStructure 并不总是需要调用,只有当结构包含某些类型的字段时。在我的情况下,我不确定一个被编组为 ByValTStr 的字符串是否需要使用 DestroyStructure。
【问题讨论】:
-
@CoolBots 不幸的是没有。我已参考该问题和解释更新了我的问题。
-
根据您的解释,我撤回了作为重复关闭的投票。我的理解是你需要调用
Marshal.DestroyStructure,因为它是一个引用类型string。不过,我不是 100% 的。我也不确定在不需要调用此方法的情况下调用此方法是否有害。我将把实际发布答案的任务留给更精通此事的人。我同意你的观点,文档并不完全清楚。 -
您可能会发现这些测试很有用(第 1 到第 3 部分):Passing a Pointer to a Structure from C# to C++ Part 1。在第 2 部分之后,您可能会认为需要调用该方法。完成第 3 部分(注意使用了哪些类型:现在您需要清楚地了解在这种情况下 blittable 和 non-blittable 类型之间的区别,以及为什么提到 SafeArrays 和 COM BSTR)。可能的话,自己做一个测试(之后你可能会得到不同的结论,但你知道为什么)。
-
@Jimi 谢谢你的链接 - 我怎么还没找到这个。几乎我需要知道的一切都在那里。我会彻底研究它,如果几天后这个问题仍然没有答案,我会根据我的学习提供答案。
-
ByValTStr + SizeConst 是预分配的(lockInfoPtr 指向的内存的一部分),所以不,您不需要调用 Marshal.DestroyStructure。实际上这种方法很少(或应该)很少使用,这取决于您的原生端,或者您希望如何在托管和原生之间进行协作。如有疑问,请在循环中运行它,有时调用 GC.Collect,并检查内存(Perfmon 的私有字节)是否随时间稳定。
标签: c# .net winapi marshalling