Я пытаюсь использовать marshalling в С#. В С++ у меня есть эта структура:
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;
}
Итак, С# eqvivalent:
[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')
Любые идеи о том, как решить эту проблему?
Это может сильно осложниться в зависимости от того, что вы пытаетесь сделать. Однако, поскольку вы работаете, это может помочь вам объявить каждый из указателей в коде С#, как это. Он использует очень полезный IntPtr, который был описан здесь ранее сегодня.:)
Обратите внимание, что это не поможет магическим образом заставить ваш код работать. Мне нужно будет увидеть гораздо больше того, что происходит, прежде чем я могу дать вам информацию об этом.
public struct aiScene
{
public uint Flags;
public IntPtr RootNode;
...
}
Основная проблема, с которой вы сталкиваетесь, заключается в том, что вы определили управляемые объекты с теми же именами, что и неуправляемые типы. Типы указателей, такие как "aiNode", должны быть определены как структуры, а не классы. Вы можете определить по-разному названные классы управляемых оболочек, которые обеспечивают управляемый доступ к лежащим в основе небезопасным данным структуры. Например:
public struct aiNode {}
public struct aiScene
{
public uint mFlags;
public unsafe aiNode* mRootNode;
// ...
}
На высоком уровне, похоже, вы пытаетесь использовать AssImp с С#. Это можно сделать сегодня, используя assimp-net. Однако, если кто-то сталкивается с подобной ситуацией и хочет получить общий ответ.
Я настоятельно рекомендую не использовать IntPtr для чего-либо, потому что они в основном являются нетипизированным void * без проверки типа. Unsafe-struct-указатели предлагают более безопасное устранение неуправляемых типов указателей. SafeHandle - еще один вариант с лучшей безопасностью и управлением некоторыми расовыми условиями. См. мою статью по теме.
Если вы буквально хотите скопировать данные из неуправляемой в управляемую землю, то для каждого типа (aiNode, aiMesh и т.д.) вам необходимо определить как небезопасную структуру (в соответствии с неуправляемым макетом), так и управляемый класс. Затем напишите (или сгенерируйте) небезопасный код, чтобы скопировать неуправляемое дерево в управляемые объекты. Обязательно будьте осторожны с любыми неуправляемыми объектами с более чем одной ссылкой.
Иногда лучшей альтернативой является создание оболочки, которая обеспечивает доступ к неуправляемым данным "на месте". Если вы делаете это "безопасно", тогда управляемые обертки должны быть тонкими объектами, которые управляют временем жизни для неуправляемых объектов и имеют свойства для доступа к их данным. Кроме того, вы можете сделать это небезопасно, просто определяя небезопасные структуры и используя их в небезопасном контексте.