2009-07-19 17 views
2

J'essaie d'utiliser le marshalling en C#. En C++ J'ai ce struct:C#: Pointeur vers la structure à l'intérieur de la structure

struct aiScene 
{ 
    unsigned int mFlags; 
    C_STRUCT aiNode* mRootNode; 
    unsigned int mNumMeshes; 
    C_STRUCT aiMesh** mMeshes; 
    unsigned int mNumMaterials; 
    C_STRUCT aiMaterial** mMaterials; 
    unsigned int mNumAnimations; 
    C_STRUCT aiAnimation** mAnimations; 
    unsigned int mNumTextures; 
    C_STRUCT aiTexture** mTextures; 
    unsigned int mNumLights; 
    C_STRUCT aiLight** mLights; 
    unsigned int mNumCameras; 
    C_STRUCT aiCamera** mCameras; 
} 

Alors, C# eqvivalent est:

[StructLayout(LayoutKind.Sequential)] 
public struct aiScene 
{ 
    public uint mFlags; 
    public unsafe aiNode* mRootNode; 
    public uint mNumMeshes; 
    public unsafe aiMesh** mMeshes; 
    public uint mNumMaterials; 
    public unsafe aiMaterial** mMaterials; 
    public uint mNumAnimations; 
    public unsafe aiAnimation** mAnimations; 
    public uint mNumTextures; 
    public unsafe aiTexture** mTextures; 
    public uint mNumLights; 
    public unsafe aiLight** mLights; 
    public uint mNumCameras; 
    public unsafe aiCamera** mCameras; 
} 

Mais beaucoup sur cette struct sont gérées (aiNode, aiMesh, aiLight), etc. Donc, j'ai cette erreur :

Cannot take the address of, get the size of, or declare a pointer to a managed type ('Assimp.aiNode')

Des idées sur la façon de résoudre ce problème?

Répondre

3

Cela pourrait devenir très compliqué en fonction de ce que vous essayez de faire. Cependant, comme vous travaillez, il pourrait vous aider à déclarer chacun des pointeurs dans le code C# comme ceci. Il utilise le very useful IntPtr, which was described on here earlier today. :)

Veuillez noter que votre code ne fonctionnera pas comme par magie. Je devrais voir beaucoup plus de ce qui se passe avant que je puisse vous donner votre avis là-dessus.

public struct aiScene 
{ 
    public uint Flags; 
    public IntPtr RootNode; 
    ... 
} 
+0

Господи, что за изврат ... лучше взять C++ \ CLI. Большое спасибо за ответ! –

+0

Utiliser IntPtr pour tous ces types devient rapidement un cauchemar, car il n'y a pas de vérification de type séparant les différents types de IntPtr. Il est préférable d'utiliser une struct * dangereuse. (définissez chaque type, tel que aiNode, en tant que type struct, puis utilisez un aiNode non sécurisé *) –

0

Le problème principal que vous rencontrez est que vous avez défini des objets gérés avec les mêmes noms que les types non gérés. Les types de pointeur, comme "aiNode", doivent être définis en tant que structs, et non en tant que classes. Vous pouvez définir différentes classes d'encapsuleurs gérés nommés qui fournissent un accès managé aux données structurées non sécurisées sous-jacentes. Par exemple:

public struct aiNode {} 
public struct aiScene 
{ 
    public uint mFlags; 
    public unsafe aiNode* mRootNode; 
    // ... 
} 

À un niveau élevé, il semble que vous essayez d'utiliser AssImp de C#. Cela peut être fait aujourd'hui en utilisant assimp-net. Cependant, dans le cas où quelqu'un se heurterait à une telle situation et voudrait une réponse générique ..

Je recommande fortement de ne pas utiliser IntPtr pour quoi que ce soit, car il s'agit essentiellement d'un vide * non typé sans vérification de type. Unsafe-struct-pointers offre une désambiguïsation plus sûre des types de pointeurs non gérés. SafeHandle est une autre option avec une meilleure sécurité et la manipulation de certaines conditions de course. Voir my article on the topic.

Si vous voulez littéralement copier les données non géré à la terre géré, pour chaque type (aiNode, aiMesh, etc.), vous devez définir à la fois un-struct dangereux (pour correspondre à la mise en page non géré), et classe gérée. Ensuite, écrivez (ou générez) du code non sécurisé pour copier l'arborescence non gérée sur les objets gérés. Soyez sûr de faire attention à tous les objets non gérés avec plus d'une référence. Parfois, une meilleure alternative consiste à écrire un wrapper qui donne accès aux données non gérées "in-place". Si vous le faites «en toute sécurité», les wrappers gérés doivent être des objets thin qui gèrent la durée de vie des objets non gérés et possèdent des propriétés permettant d'accéder à leurs données. Alternativement, vous pouvez le faire de manière imprévisible en définissant simplement les structures dangereuses et en les utilisant dans un contexte dangereux.

Questions connexes