2

これまで見てきた例のどれも、再帰参照を含む構造体の共用体を含む構造体のマーシャリングの問題に対処しているようには見えません。これらを含む構造体のマーシャラーを作成しようとしていますが、これまでのところ失敗しています。

例えば:

typedef enum {
    My_StructA = 0x7878,
    My_StructB
} MyStructTag;

 typedef struct _MyStruct MyStruct;  

 struct _MyStruct {  
     MyStructTag discriminator;  
     union {  
        struct {  
            int a;  
            int b;  
        } StructA;  

        struct {  
            int c;  
            MyStruct* d;  
        } StructB;
    } MyUnion;  
};

次のように構造を定義しようとしました。

type MyStructTag =
    | My_StructA = 0x7878
    | My_StructB = 0x7879

[<Struct; StructLayout(LayoutKind.Sequential)>]
type StructA =
    val mutable a : int
    val mutable b : int

[<Struct; StructLayout(LayoutKind.Sequential)>]
type StructB =
    val mutable c : int
    val mutable d : MyStruct

[<Struct; StructLayout(LayoutKind.Explicit)>]
type MyStruct =
    [<FieldOffset(0)>] val discriminator : MyStructTag
    [<FieldOffset(4)>] val structA : StructA
    [<FieldOffset(4)>] val structB : StructB

MyStruct を明示的に定義した理由は、この構造体のカスタム マーシャラーを作成するときに Marshal.OffsetOf() と Marshal.SizeOf() を使用できるようにするためです。私が見た限りでは、カスタム マーシャラーを作成することがユニオンを処理する唯一の方法です。私がそれについて間違っている場合は、参考にしていただければ幸いです。

上記のコードを書いているときに受け取るエラーは次のとおりです。

error FS0039: The type 'MyStruct' is not defined

これは、再帰的に定義できるのは判別共用体型だけだからだと思います。ただし、F# でこれらの構造を表現する他の方法は知りません。

よろしくお願いいたします。

4

1 に答える 1

4

2 つの問題があります。まず、相互に再帰的な型 (識別された共用体、クラス、または構造体のいずれであっても) を使用して定義する必要があります。

type A = ... 
and B = ...

それよりも

type A = ... 
type B = ...

type(また、属性は単語の前または後に置くことができますが、単語の後にのみあることに注意してくださいand...)。ただし、これを試してみると、構造体は互いのフィールドとして直接再帰できないため、別のエラーが発生することがわかります。構造体 A に構造体 B であるフィールドがあり、構造体 B に構造体 A であるフィールドがある (そして、それらのいずれかに他のフィールドがある) 場合、サイズは無限になります。これは C コードにも当てはまることに注意してください。それ自体ではなく、へのポインタStructBが含まれています。.NET では、これに を使用できます。F# では、エイリアスまたはを使用できます。これを試して:MyStructMyStructIntPtrnativeintnativeptr<MyStruct>

open System.Runtime.InteropServices

type MyStructTag =
| My_StructA = 0x7878
| My_StructB = 0x7879

[<Struct; StructLayout(LayoutKind.Sequential)>]
type StructA =
  val mutable a : int
  val mutable b : int

[<Struct; StructLayout(LayoutKind.Sequential)>]
type StructB =
  val mutable c : int
  val mutable d : nativeptr<MyStruct>

and [<Struct; StructLayout(LayoutKind.Explicit)>]MyStruct =
    [<FieldOffset(0)>] val discriminator : MyStructTag
    [<FieldOffset(4)>] val structA : StructA
    [<FieldOffset(4)>] val structB : StructB
于 2011-01-11T03:41:25.707 に答える