2009-04-08 8 views
4

Tout, cela est un suivi d'une question précédente ici: C# formatting external Dll function parametersComment convertir un IntPtr de nouveau dans un objet

Voici plus précisément le code que je suis en train de convertir en 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); 

La fonction "FILES_GetMemoryMapping" est appelée deux fois, je devine la première fois pour obtenir la taille de la structure, et la seconde pour le remplir réellement. Le "pMapping" est un pointeur sur une structure en C++. Dans mon code C#, j'ai pMapping comme type IntPtr.

La ligne suivante que je peux convertir en:

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

Avec (UM0516.Mapping) étant la structure. Cool, donc je viens d'allouer de l'espace que IntPtr pointe vers. Maintenant pour la ligne suivante ... "pMapping-> NbSectors = 0;"

Comment est-ce que je suis supposé aller dans l'espace de mémoire non géré maintenant alloué, tapez l'a moulé comme struct (UM0516.Mapping), et placez un de ses membres? Ensuite, assurez-vous que je n'ai pas trop de vis pour que la deuxième fois que j'appelle "FILES_GetMemoryMapping", il peut maintenant utiliser cette structure?

- Ok, je l'ai pris quelques conseils et maintenant ceci:

J'ai essayé et j'obtenir un « AccessViolationException était non gérée » exception sur le premier appel

« FILES_GetMemoryMapping » Voici ce que J'ai:

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); 

Pensez-vous que cette exception provient du paramètre "pMapping"? Cela pourrait-il provenir de n'importe quoi d'autre que j'ai passé?

Répondre

10

Afin d'obtenir le IntPtr, ce que vous voulez faire est de créer la structure, définissez les options que vous devrez peut-être, allouer la mémoire comme vous avez déjà, appelez ..

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

Cela va copier les données de votre structure peuplée dans votre mémoire allouée.

Pour copier les données de la mémoire dans une nouvelle structure nommée « mapping », appelez ...

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

Pour convertir un IntPtr retour à un objet, j'ai utilisé une méthode qui fait cela:

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 une liste de GCHandles unfreed qui sont libérées automatiquement lorsque les poignées sont disposées ou finialized)

Questions connexes