2009-07-19 5 views
2

C#에서 마샬링을 사용하려고합니다.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) 그래서,이 오류가 관리됩니다

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#을 eqvivalent은 다음과 같습니다 C++에서 나는이 구조체를 :

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

이 문제를 해결하는 방법에 대한 아이디어가 있으십니까?

답변

3

이 작업은 수행하려는 작업에 따라 매우 복잡해 질 수 있습니다. 그러나 작업하면서 C# 코드에서 각 포인터를 이와 같이 선언하는 데 도움이 될 수 있습니다. very useful IntPtr, which was described on here earlier today을 사용합니다. :)

마술처럼 코드를 작동시키지 않습니다. 나는 당신에게 그것에 대한 정보를 줄 수 있기 전에 계속되고있는 일들을 더 많이 볼 필요가 있습니다.

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

C++ \ CLI. Большое спасибо за ответ! –

+0

IntPtr의 다른 유형을 구분하는 유형 확인이 없기 때문에 이러한 모든 유형의 IntPtr을 사용하면 곧 악몽이됩니다. 안전하지 않은 struct *를 사용하는 것이 좋습니다. (aiNode와 같은 각 유형을 구조체 유형으로 정의한 다음 안전하지 않은 aiNode *를 사용하십시오) –

0

주요 문제는 관리되지 않는 유형과 동일한 이름으로 관리되는 개체를 정의했다는 것입니다. "aiNode"와 같은 포인터 유형은 클래스가 아니라 구조체로 정의되어야합니다. 기본이되는 안전하지 않은 구조체 데이터에 대한 관리 된 액세스를 제공하는 다르게 명명 된 관리되는 래퍼 클래스를 정의 할 수 있습니다. 예 :

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

높은 수준에서 보면 C#의 AssImp를 사용하려고하는 것처럼 보입니다. 오늘 assimp-net을 사용하여이를 수행 할 수 있습니다. 그러나 누군가가 이와 같은 마샬링 상황에 빠지면 일반적인 대답을 원할 것입니다.

기본적으로 타입 검사가없는 타입이없는 void *이므로 IntPtr을 사용하지 말 것을 강력히 권장합니다. 안전하지 않은 구조체 포인터는 관리되지 않는 포인터 유형을 안전하게 구분합니다. SafeHandle은 일부 경쟁 조건에 대한보다 나은 안전과 처리 방법을 제공합니다. my article on the topic을 참조하십시오.

당신이 (관리되지 않는 레이아웃에 맞게) 안전하지 않은-구조체 모두를 정의 할 필요가 다음 각 유형 (aiNode, aiMesh 등)에 대한 관리, 토지 관리되지 않는에서 데이터를 복사에 말 그대로 원하는 경우

하고, 관리되는 클래스. 그런 다음 관리되지 않는 트리를 관리되는 개체로 복사하는 안전하지 않은 코드를 작성하거나 생성하십시오. 하나 이상의 참조가있는 관리되지 않는 객체를주의하십시오.

경우에 따라 관리되지 않는 데이터에 대한 "현재 위치"에 대한 액세스를 제공하는 래퍼를 작성하는 것이 좋습니다. "안전하게"수행하는 경우 관리되는 래퍼는 관리되지 않는 개체의 수명을 관리하고 해당 데이터에 액세스 할 수있는 속성이있는 씬 개체 여야합니다. 또는 unsafe 구조체를 정의하고 안전하지 않은 컨텍스트에서 사용하는 방법으로 안전하지 않게 할 수도 있습니다.

관련 문제