C#互操作驱动和处理方式

3
我有一个DLL,它是用C++编写的,包含在一个C#项目中,但我发现AccessViolationExceptions异常出现得不可理喻。我怀疑我的垃圾回收不正确。我有一个非托管方法apiGetSettings(来自DLL),应该将数据复制到Settings对象中(实际上是原始代码中的结构体,但.NET InterOp只允许导入数据作为类对象)。我使用System.Runtime.InteropServices.Marshal方法来分配和释放内存,但可能会留下垃圾导致一切崩溃。

现在,我应该在Settings类中实现IDisposable方法吗(它是非托管的)?如果是这样,我该如何处理作为UnmanagedType.ByValTStr封送的字符串,以及如何处理Settings对象?

using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
class Settings
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 33)]
internal string d;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
internal string t;
internal int b;
}

[DllImport(".\\foobar.dll", EntryPoint = "getSettings")]
private static extern int apiGetSettings(IntPtr pointerToSettings);

void GetSettings(ref Settings settings)
{
int debug = 0;

// Initialize a pointer for the structure and allocate memory
IntPtr pointerToSettings = Marshal.AllocHGlobal(43);

// Connect the pointer to the structure
Marshal.StructureToPtr(settings, pointerToSettings, true);

// Point the pointer
debug = apiGetSettings(pointerToSettings);

// Copy the pointed data to the structure
Marshal.PtrToStructure(pointerToSettings, settings);

// Free the allocated memory
Marshal.FreeHGlobal(pointerToSettings);
}
1个回答

1

不需要实现IDisposable接口。你的Settings类是托管类(那些属性只是为了运行时目的),会被垃圾回收。

我的第一个猜测:你分配了43个字节,但是你的两个字符串加起来超过70个字节(记住,除非你在古老的Win98/Me上,否则一个字符的大小为2个字节),所以你没有分配足够的空间。使用Marshal.SizeOf动态确定结构体的大小。


谢谢你,我的救星!否则我永远想不到那个。这解决了我过去三个月所有的问题。 :) - Olli Heikkinen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接