【问题标题】:C#: Pointer to the struct inside the structC#:指向结构内部结构的指针
【发布时间】:2009-07-19 02:16:26
【问题描述】:

我正在尝试在 C# 中使用编组。在 C++ 中,我有一个这样的结构:

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

所以,C# 等效为:

[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;
}

但是这个结构上的很多都是托管的(aiNode、aiMesh、aiLight)等等。所以,我有这个错误:

无法获取地址,获取 的大小,或声明一个指向 托管类型('Assimp.aiNode')

关于如何解决这个问题的任何想法?

【问题讨论】:

    标签: c# marshalling


    【解决方案1】:

    这可能会变得非常复杂,具体取决于您要执行的操作。但是,在您工作时,它可以帮助您像这样在 C# 代码中声明每个指针。它使用very useful IntPtr, which was described on here earlier today。 :)

    请注意,这不会神奇地让您的代码正常工作。在我给你提供意见之前,我需要了解更多正在发生的事情。

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

    【讨论】:

    • Господи, что за изврат...лучше взять C++\CLI。 Большое спасибо за ответ!
    • 对所有这些类型使用 IntPtr 很快就会变成一场噩梦,因为没有类型检查来区分不同类型的 IntPtr。最好使用不安全的结构 。 (将每种类型,如aiNode,定义为struct类型,然后使用不安全的aiNode
    【解决方案2】:

    您遇到的主要问题是您定义了与非托管类型同名的托管对象。指针类型,如“aiNode”,应该定义为结构,而不是类。您可以定义不同命名的托管包装类,它们提供对底层不安全结构数据的托管访问。例如:

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

    在高层次上,您似乎正在尝试使用 C# 中的 AssImp。这可以在今天使用assimp-net 完成。但是,如果有人遇到这样的编组情况并想要一个通用的答案..

    我强烈建议不要将 IntPtr 用于任何事情,因为它们基本上是没有类型检查的无类型 void*。 Unsafe-struct-pointers 提供了对非托管指针类型的更安全的消歧。 SafeHandle 是另一个选项,具有更好的安全性和对某些竞争条件的处理。见my article on the topic

    如果您真的想复制将数据从非托管土地复制到托管土地,那么对于每种类型(aiNode、aiMesh 等),您需要同时定义一个 unsafe-struct(以匹配非托管布局) 和托管类。然后,编写(或生成)不安全代码以将非托管树复制到托管对象。请务必小心任何具有多个引用的非托管对象。

    有时更好的选择是编写一个包装器,它提供对“就地”非托管数据的访问。如果您“安全”地进行操作,那么托管包装器应该是管理非托管对象的生命周期并具有访问其数据的属性的瘦对象。或者,您可以通过仅定义不安全的结构并在不安全的上下文中使用它们来不安全地执行此操作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-09-11
      • 1970-01-01
      • 2018-01-29
      • 2021-02-02
      • 1970-01-01
      • 2017-01-04
      • 2012-07-16
      相关资源
      最近更新 更多