2011-11-04 17 views
2

Beckhoff-PLCからc#クラスにアラーム構造を読み込もうとしています。 まず、私はC#でまったく同じ構造を確認する必要があり、それは現在、次のようになります。私の問題を引き起こしていただきました!MarshalAsAttribute文字列の配列

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
    public class Alarm 
    { 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 81)] 
     public string text; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)] 
     public string objectName; 
     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] 
     public string[] instancePath = new string[6]; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)] 
     public string timeStamp; 
     public int priority; 
     [MarshalAs(UnmanagedType.I1)] 
     public bool acknowledge; 
     [MarshalAs(UnmanagedType.I1)] 
     public bool disabled; 
     [MarshalAs(UnmanagedType.I1)] 
     public bool alarmIn; 
    } 

は「instancePath」フィールドです。 フィールドが文字列の場合、SizeConstで「UnmanagedType.ByValTStr」属性を使用できます。配列が「UnmanagedType.ByValArray」の場合でも、文字列[]を使用する場合は、何をすべきかわかりません。

私は新しいクラスを作成しようとしました:

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
    public class Alarm 
    { 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 81)] 
     public string text; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)] 
     public string objectName; 
     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] 
     public InstancePathDefinition[] instancePath = new InstancePathDefinition[6]; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)] 
     public string timeStamp; 
     public int priority; 
     [MarshalAs(UnmanagedType.I1)] 
     public bool acknowledge; 
     [MarshalAs(UnmanagedType.I1)] 
     public bool disabled; 
     [MarshalAs(UnmanagedType.I1)] 
     public bool alarmIn; 
    } 

しかし、私は私のアラームクラスにMarshal.SizeOfを使用する場合、それは私に与える:

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
    public class InstancePathDefinition 
    { 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)] 
     public string instancePath; 
    } 

そして、私のアラームクラスで使用私が期待するように、189バイトではなく、147バイトとなります。

EDIT: 私はサイズの違いの理由は、配列だけが開始され、クラス "InstancePathDefinition"はしないと思う。

クラスから構造体に変更しようとしましたが、サイズが一致しました。

私はUnmanagedType.ByValArrayとUnmanagedType.ByValTStrの両方を異なるSizeConstのサブタイプとして組み合わせることはできませんが、それでもなお奇妙です。

次は、アラームクラスの配列を作成する必要があり、同じ問題に再び遭遇します。

+0

代わりに、固定サイズのchar配列を試してみることもできます(別名char [66])。配列内の固定オフセットにあるため、探している6個の文字列を抽出するためにヘルパー関数をクラスに追加できます。 – user957902

+0

来るテキストデータは、データのユニコードまたはASCIIですか?そのアスキーなら、文字セットを設定する必要があります。 – user957902

+0

ありがとうございましたuser957902、IveはPLCから正しい文字列を取得していることを確認しましたので、文字セットを変更する必要はありません。 – user1029697

答えて

2

クラスオブジェクトの配列の代わりに構造体の配列にします。

[StructLayout(LayoutKind.Sequential)] 
public struct InstancePathDefinition { 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)] 
    public string path; 
} 

私が試したところでMarshal.SizeOf()が返されました。