2

我正在尝试在 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') 的地址、大小或声明指向托管类型的指针

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

4

2 回答 2

3

根据您要执行的操作,这可能会变得非常复杂。但是,在您工作时,它可以帮助您像这样在 C# 代码中声明每个指针。它使用了非常有用的 IntPtr,今天早些时候在这里进行了描述。:)

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

public struct aiScene
{
    public uint Flags;
    public IntPtr RootNode;
    ...
}
于 2009-07-19T02:34:51.043 回答
0

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

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

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

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

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

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

于 2014-10-22T19:35:34.817 回答