Comment puis-je marshall struct récursive à c forte?
-
18-09-2019 - |
Question
J'ai une struct non gérée Je voudrais maréchal c forte qui ressemble essentiellement à ceci:
struct MyStruct{
/* ... some stuff ... */
int numChilds;
MyStruct *childs;
}
Je crois que je dois écrire un placier personnalisé mais je ne suis pas sûr de la façon de procéder.
La solution
J'aime utiliser une configuration comme ça quand je ne ai pas besoin pour les enfants d'index directement:
struct MyStruct
{
/* ... some stuff ... */
int numChilds;
IntPtr childData;
public IEnumerable<MyStruct> Children
{
get
{
int elementSize = Marshal.SizeOf(typeof(MyStruct));
for (int i = 0; i < this.numChilds; i++)
{
IntPtr data = new IntPtr(this.childData.ToInt64() + elementSize * i);
MyStruct child = (MyStruct)Marshal.PtrToStructure(data, typeof(MyStruct));
yield return child;
}
}
}
}
Si vous Bougez besoin, la chose la plus facile directement les enfants d'index crée une méthode GetChild
(ci-dessous). La façon la plus difficile est de créer une classe aide / wrapper qui implémente IList<MyStruct>
. Une instance serait revenu de la propriété Children
, et son travail interne serait en appelant la méthode de GetChild
. Ceci est laissé en exercice au lecteur devrait-il avoir besoin.
public MyStruct GetChild(int index)
{
if (index < 0)
throw new ArgumentOutOfRangeException("index", "The index must be >= 0.");
if (index >= this.numChilds)
throw new ArgumentException("The index must be less than the number of children", "index");
int elementSize = Marshal.SizeOf(typeof(MyStruct));
IntPtr data = new IntPtr(childData.ToInt64() + elementSize * index);
MyStruct child = (MyStruct)Marshal.PtrToStructure(data, typeof(MyStruct));
return child;
}
Autres conseils
Si vous voulez juste passer à une fonction non géré, vous pouvez simplement utiliser le code dangereux et stackalloc / fixer un tableau pour obtenir un pointeur sur le tableau d'objets.
unsafe struct Foo
{
public int value;
public int fooCount;
public Foo* foos;
}
[DllImport("dll_natv.dll")]
static extern void PrintFoos(Foo f);
public unsafe static void Main()
{
Foo* foos = stackalloc Foo[10];
for (int i = 0; i < 10; ++i)
foos[i].value = i;
Foo mainFoo = new Foo();
mainFoo.fooCount = 10;
mainFoo.value = 100;
mainFoo.foos = foos;
PrintFoos(mainFoo);
}