2012-02-17 1 views
0

Problème:Impossible struct unmarshal du code non managé dans Mono

Je peux rassembler avec succès un struct avec des éléments de racines ainsi que les éléments du tableau dans le code non managé, mais ne peut pas obtenir les données de l'élément racine arrière (les éléments du tableau venir retour correct). J'ai essayé un certain nombre d'approches, mais aucune n'a fonctionné jusqu'à présent. Voici le plus simple ci-dessous.

J'ai lu à http://www.mono-project.com/Interop_with_Native_Libraries et penser que je fais tout correctement (mais évidemment pas ;-)

Mise en œuvre:

C#: déclarations

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
private struct Vector3 
{ 
    public float x; 
    public float y; 
    public float z; 
} 

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
private struct MeshData 
{ 
    [MarshalAs(UnmanagedType.LPArray)] 
    public Vector3[] vertices; 
    public int verticeCount; 
} 

[DllImport("MeshPlugin")] 
private static extern bool ImportMesh([In, Out, MarshalAs(UnmanagedType.LPStruct)] MeshData meshData); 

déclarations autochtones C:

#pragma pack(1) 
typedef struct VECTOR3 
{ 
    float x; 
    float y; 
    float z; 
} VECTOR3; 

#pragma pack(1) 
typedef struct MESHDATA 
{ 
    VECTOR3 *vertices; 
    int verticeCount; 
} MESHDATA; 

appelé de C# comme ceci:

<defined vertices and length...> 

MeshData meshData = new MeshData(); 
meshData.vertices = mesh.vertices; // note that vertices[0].x = 111 
meshData.verticeCount = 1; 
ImportMesh(meshData); // calls native function 
Debug.Log(meshData.vertices[0].x); // prints 222 which is correct, so array got marshaled back okay 
Debug.Log(meshData.verticeCount); // **prints 1 which is incorrect** so the int element did not come back okay 

Implémentation native:

bool ImportMesh(MESHDATA *meshData) 
{ 
    printf("%f", meshData->vertices[0].x); // prints 111 which is correct 
    meshData->vertices[0].x = 222; // change to see if it gets back okay 
    printf("%d", meshData->verticeCount); // prints 1 which is correct 
    meshData->verticeCount = 2; // change to see if it gets back okay 
    return true; 
} 

Le problème est que les valeurs sous-tableau de struct sont correctement retournés, mais que les principaux éléments struct ne sont pas.

J'ai aussi essayé cela en C#:

[DllImport("MeshPlugin")] 
private static extern bool ImportMesh(IntPtr meshData); 

int size = Marshal.SizeOf(typeof(MeshData)); 
IntPtr pMeshData = Marshal.AllocHGlobal(size); 
Marshal.StructureToPtr(meshData, pMeshData, false); 
ImportMesh(pMeshData); 
meshData = (MeshData)(Marshal.PtrToStructure(pMeshData, typeof(MeshData))); 
Marshal.FreeHGlobal(pMeshData);  

Et celui-ci se bloque mal sur le retour (mais le journal indique que le code natif exécuté et imprimé les valeurs correctes du côté natif).

J'ai essayé d'autres permutations avec des décorateurs d'attributs, etc., mais le compilateur mono a suggéré de supprimer certains des attributs car ils n'étaient pas nécessaires, ce que j'ai fait.

J'ai été googler et craquer ma tête sur ceci pendant 2 jours maintenant, et n'importe quelle aide est très appréciée!

Répondre

2

Je n'ai pas essayé, mais c'est la façon dont je voudrais tout d'abord essayer de le faire:

[DllImport("MeshPlugin")] 
private static extern bool ImportMesh(ref MeshData meshData); 

et si cela ne fonctionne toujours pas, je vais essayer de changer la déclaration de struct :

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
private struct MeshData 
{ 
    public IntPtr vertices; 
    public int verticeCount; 
} 
MeshData meshData = new MeshData(); 
meshData.vertices = Marshal.AllocHGlobal (...); 
// copy vertex data to the unmanaged array 
meshData.verticeCount = 1; 
+0

Merci Rolf. La chose amusante est que le tableau des sommets fonctionne déjà, ce sont les ints dans la structure qui ne le sont pas. Dans votre changement suggéré, je ne vois aucun changement dans la façon dont le verticeCount est marshalé? À votre santé! –

+0

Un paramètre ref n'est pas nécessairement appelé de la même manière qu'un paramètre [In, Out, MarshalAs (UnmanagedType.LPStruct)] :) –

+0

Mais dites-vous que je dois faire le Marshal.AllocHGlobal sur tout? Par exemple. le MeshData obtient un Marshal.AllocHGlobal et aussi le tableau vertices obtient un distinct? –

Questions connexes