我在C#中使用IntPtr,从C ++项目中获取对象数组。
为此,我分配了Marshal.AllocHGlobal方法所需的内存,并且我将C ++中的完整数组复制到ptr中。
问题是我正在推广指针,移动到数组中的下一个对象。
我的问题是: 在使用Marshal.FreeHGlobal方法之前,我是否必须恢复IntPtr的第一个值?
这是代码
public List<DirEntry> getDirEntries()
{
int dirEntrySize = Marshal.SizeOf(typeof(DirEntry));
int bufferSize = 28 * dirEntrySize;
IntPtr buffer = Marshal.AllocHGlobal(bufferSize);
CppToCsharpAdapter.getDirEntries(this.myDiskPointer, buffer);
DirEntry dirEntry = new DirEntry();
List<DirEntry> dirEntries = new List<DirEntry>();
for (int i = 0; i < 28; i++)
{
Marshal.PtrToStructure(buffer, dirEntry);
buffer += dirEntrySize;
}
Marshal.FreeHGlobal(buffer);
return dirEntries;
}
答案 0 :(得分:2)
您必须创建原始指针的副本,以后可以使用。在这种情况下,它被称为current:
public List<DirEntry> getDirEntries()
{
int dirEntrySize = Marshal.SizeOf(typeof(DirEntry));
int bufferSize = 28 * dirEntrySize;
IntPtr buffer = Marshal.AllocHGlobal(bufferSize);
CppToCsharpAdapter.getDirEntries(this.myDiskPointer, buffer);
IntPtr current = buffer;
DirEntry dirEntry = new DirEntry();
List<DirEntry> dirEntries = new List<DirEntry>();
for (int i = 0; i < 28; i++)
{
Marshal.PtrToStructure(current, dirEntry);
current += dirEntrySize;
}
Marshal.FreeHGlobal(buffer);
return dirEntries;
}
但是,如果不使用指针的显式副本,则可以使用IntPtr.Add()
:
public List<DirEntry> getDirEntries()
{
int dirEntrySize = Marshal.SizeOf(typeof(DirEntry));
int bufferSize = 28 * dirEntrySize;
IntPtr buffer = Marshal.AllocHGlobal(bufferSize);
CppToCsharpAdapter.getDirEntries(this.myDiskPointer, buffer);
DirEntry dirEntry = new DirEntry();
List<DirEntry> dirEntries = new List<DirEntry>();
for (int i = 0; i < 28; i++)
{
Marshal.PtrToStructure(IntPtr.Add(buffer, i * dirEntrySize), dirEntry);
}
Marshal.FreeHGlobal(buffer);
return dirEntries;
}
请记住,您的代码包含潜在的内存韭菜。您应该将代码包装在try / finally块中。在finally块中,如果指针不为零,则再次释放内存块:
public List<DirEntry> getDirEntries()
{
int dirEntrySize = Marshal.SizeOf(typeof(DirEntry));
int bufferSize = 28 * dirEntrySize;
IntPtr buffer = Marshal.AllocHGlobal(bufferSize);
try
{
CppToCsharpAdapter.getDirEntries(this.myDiskPointer, buffer);
DirEntry dirEntry = new DirEntry();
List<DirEntry> dirEntries = new List<DirEntry>();
for (int i = 0; i < 28; i++)
{
Marshal.PtrToStructure(IntPtr.Add(buffer, i * dirEntrySize), dirEntry);
}
}
finally
{
if (buffer != IntPtr.Zero)
Marshal.FreeHGlobal(buffer);
}
return dirEntries;
}