2009-04-08 62 views
4

所有,这是从以前的问题在这里的后续行动:C# formatting external Dll function parameters如何一个IntPtr转换回对象

这里明确的是,我想转换为C#代码:

FILES_GetMemoryMapping((LPSTR)(LPCTSTR)MapFile, &Size, (LPSTR)MapName, &PacketSize, pMapping, &PagePerSector); 
// Allocate the mapping structure memory 
pMapping = (PMAPPING)malloc(sizeof(MAPPING)); 
pMapping->NbSectors = 0; 
pMapping->pSectors = (PMAPPINGSECTOR) malloc((Size) * sizeof(MAPPINGSECTOR)); 

// Get the mapping info 
FILES_GetMemoryMapping((LPSTR)(LPCTSTR)MapFile, &Size, (LPSTR)(LPCTSTR)MapName, &PacketSize, pMapping, &PagePerSector); 

函数“FILES_GetMemoryMapping”被调用两次,我猜第一次得到结构的大小,第二次实际填充它。

“pMapping”是一个指向C++结构体的指针,在我的C#代码中,我有pMapping类型为IntPtr。下一行我可以转换为:

pMapping = Marshal.AllocHGlobal(Marshal.SizeOf(new UM0516.Mapping())); 

(UM0516.Mapping)是结构体。很酷,所以我刚刚分配了一些IntPtr指向的空间。现在为下一行......“pMapping-> NbSectors = 0;”

我想如何进入现在分配的非托管内存空间,类型将其转换为(UM0516.Mapping)结构,并设置其成员之一?然后确保我没有太多的使用它,这样第二次我调用“FILES_GetMemoryMapping”,它现在可以使用这个结构?

- 好吧,我已经采取了一些意见,现在有这样的:

我尝试这样做,我得到一个“AccessViolationException是未处理的”第一个“FILES_GetMemoryMapping”异常调用

这里是什么我有:

string filepath = @"C:\blah.blah"; 
string MapFile = @"D:\blah.blah"; 
UM0516.Mapping myMapping = new UM0516.Mapping(); 
IntPtr pMapping = Marshal.AllocHGlobal(Marshal.SizeOf(myMapping)); 
Marshal.StructureToPtr(myMapping, pMapping, false); 
ushort PacketSize = 0; 
ushort size = 0; 
string MapName = String.Empty; 
byte PagePerSector = 0; 

uint b7 = UM0516.FILES_GetMemoryMapping(MapFile, out size, MapName, out PacketSize, pMapping, out PagePerSector); 

您是否认为此异常来自“pMapping”参数?这可能来自我通过的其他任何东西吗?

回答

10

为了获得IntPtr的,你会想要做的是创造你的结构,设置您可能需要,分配内存像你已经有了,然后调用任何选项..

System.Runtime.InteropServices.Marshal.StructureToPtr(yourStructVariable, pMapping, false); 

这会将您填充结构中的数据复制到您分配的内存中。

要从内存中的数据复制到一个名为“mapping”,称新的结构......

UM0516.Mapping mapping = (UM0516.Mapping)System.Runtime.InteropServices.Marshal.PtrToStructure(pMapping, typeof(UM0516.Mapping)) 
0

要一个IntPtr转换回一个对象,我用做这个的方法:

if (ptrToUnwrap == IntPtr.Zero) 
    return null; 
GCHandle handle = (GCHandle)ptrToUnwrap; 
object handledObj = handle.Target; 
if (handles.unfreed.Contains(handle)) 
    handles.unfreed.Remove(handle); 
handle.Free(); 
return handledObj; 

(handles.unfreed是未处理的GCHandles的列表,当手柄处置或终止时会自动释放)