2016-12-02 11 views
1

私はこれまでの問題の答えを見てきましたが、まだ固執しています。私は収集し、ushortの配列を含む構造体の3つの配列を処理する必要があります。配列を含む構造体の配列

Error 1 'Wvsamps.wav1': cannot have instance field initializers in structs C:\Users\Hewitt\Desktop\C# Projects\MarshalBytesToStruct\LoadSamps.cs 8 11 MarshalBytesToStruct 

私は、その後アクセスし、自分のメインプログラムクラスから構造体の私の配列に値を入れたいと思います:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

struct Wvsamps 
{ 
    ushort[] wav1 = new ushort[3]; 
    ushort[] wav2 = new ushort[3]; 
    ushort[] wav3 = new ushort[3]; 
    ushort[] wav4 = new ushort[3]; 
    ushort modes; 
    uint time; 
    ushort chkSum; 
}  


namespace ConsoleApplication1 
{ 
    public class LoadSamps 
    { 
     Wvsamps[] ldSamps = new Wvsamps[0x800000]; 
    } 
} 

コンパイラはエラーを与える:私は私の構造体を保持するクラスを作りました。私はWindowsフォームアプリケーションでこれを行うためのハンドルを取得しようとするコンソールアプリケーションとしてこれをやっています。

私の問題を拡大するために、ネットワーク接続で1秒あたり32バイトのパケットを受信します。私は私のオリジナルのポストに示すようにWvsamps構造体の配列でそれらを配置する必要があり、これらの32個のバイトのパケットを受信すると

0x94, 0xa5, 0xca, 0x62, 0x41, 0x28, 0x4c, 0x93, 0x09, 0x42, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x04, 0x01, 0x40, 0x10, 0x00, 0x00, 0x70, 0x0d, 0x58, 0x3e, 0xc6, 0xd1, 0x07, 

:32バイトのパケットの実際のデータは次のようになります。理想的には、Wvsamps構造体は32バイト長です。これの古いC/C++組み込みソリューションでは、32バイトのネットワークパケットをldSamps配列のWvsamps構造体にmemcpyでき、次に受け取ったパケットのldSamps配列の次の利用可能なWvsamps構造体を指すようにldSamps配列インデックスをインクリメントしました。私はldSamps配列の0x40000分のWvsamps構造体を累積する必要がありますので、配列は0x40000 Wvsamps構造体にする必要があります。

私は波形をWinFormにプロットするためにldSamps配列からWvsamps構造体にアクセスし、波形をスクロールして(少なくともハードコードされたシミュレーションデータで動作するようにしています)、測定を行います。また、私が受け取っているデータがBig Endian形式で来て、Wvsamps構造体のLittle Endianに変換して格納する必要があるという追加の問題があります。

+0

'Wvsamps'をクラスにして、問題がなくなります。あなたが構造体が必要だと思った特別な理由は何ですか? –

+0

過去のCプログラミングから解決策を動かそうとしています。各構造体は1秒分のWvsampを表し、72時間以上で最大8メガバイトを収集する必要があります。私はいくつかのコードを残し、Wvsamps構造体の3つのldSamps配列を宣言する必要があります。各8Megのサイズです。私はLoadSampsをクラスにすることでこれを行う必要があると思っていました。 –

+0

最新のマシンでは、扱っているオブジェクトのサイズに問題はありません。クラスを使用するだけで、初期化が可能になります。 –

答えて

0

安全でないバッファを使用する試みがありますが、試みたことはありません。安全でないコードが必要です。ここで(プロジェクトの設定)

unsafe struct Wvsamps 
{ 
    fixed ushort wav1[3]; 
    fixed ushort wav2[3]; 
    fixed ushort wav3[3]; 
    fixed ushort wav4[3]; 
    ushort modes; 
    uint time; 
    ushort chkSum; 
}  
+0

私は安全ではなく、プロジェクトプロパティ - ビルドを設定して安全でないコードを許可しようとしましたが、同じコンパイラエラーが発生します。 –

+0

@ DaleH.あなたは、構造体の定義を答えと同じに変更する必要があります。 –

+0

構造体も安全でないとマークする必要があります。 @デールのように言った。 –

1

速いが、不格好になるだろうfixedアレイを使用したソリューションです。ここ

[StructLayout(LayoutKind.Sequential)] 
unsafe struct Wvsamps 
{ 
    const int Size = 3; 
    fixed ushort wav1[Size]; 
    fixed ushort wav2[Size]; 
    fixed ushort wav3[Size]; 
    fixed ushort wav4[Size]; 
    public ushort modes; 
    public uint time; 
    public ushort chkSum; 

    public ushort this[int wav, int index] 
    { 
     get 
     { 
      if (index<0||index>=Size) 
      { 
       throw new IndexOutOfRangeException("index"); 
      } 
      switch (wav) 
      { 
       case 0: 
        fixed (ushort* ptr = wav1) { return ptr[index]; } 
       case 1: 
        fixed (ushort* ptr = wav2) { return ptr[index]; } 
       case 2: 
        fixed (ushort* ptr = wav3) { return ptr[index]; } 
       case 3: 
        fixed (ushort* ptr = wav4) { return ptr[index]; } 
       default: 
        throw new IndexOutOfRangeException("wav"); 
      } 
     } 
     set 
     { 
      if (index<0||index>=Size) 
      { 
       throw new IndexOutOfRangeException("index"); 
      } 
      switch (wav) 
      { 
       case 0: 
        fixed (ushort* ptr = wav1) { ptr[index]=value; } 
        break; 
       case 1:          
        fixed (ushort* ptr = wav2) { ptr[index]=value; } 
        break; 
       case 2:          
        fixed (ushort* ptr = wav3) { ptr[index]=value; } 
        break; 
       case 3:          
        fixed (ushort* ptr = wav4) { ptr[index]=value; } 
        break; 
       default: 
        throw new IndexOutOfRangeException("wav"); 
      } 
     } 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Wvsamps[] ldSamps = new Wvsamps[0x800000];    

     for (int i = 0; i<ldSamps.Length; i++) 
     { 
      Wvsamps sample=new Wvsamps(); 

      sample.time=(uint)i; 
      sample.modes=1; 
      //wav1 = [1,2,3] 
      sample[0, 0]=1; 
      sample[0, 1]=2; 
      sample[0, 2]=3; 
      //wav2 = [4,5,6] 
      sample[1, 0]=4; 
      sample[1, 1]=5; 
      sample[1, 2]=6; 
      //wav3 = [7,8,9] 
      sample[2, 0]=7; 
      sample[2, 1]=8; 
      sample[2, 2]=9; 
      //wav4 = [10,11,12] 
      sample[3, 0]=10; 
      sample[3, 1]=11; 
      sample[3, 2]=12; 

      // VERY IMPORTANT 
      // Structs needs to be assigned with one statement as a whole 
      ldSamps[i]=sample; 

      // You cannot do this, ldSamps[i].time = 10 
     } 
    } 
} 
+0

このコードは、より身近な感じがするので、私には意味があります。私はあなたが表示したように物事を設定することができると思うし、メインのfor(;;)ループを持っている場所私はイベントを使用して、サンプルとモードと時刻を取得した値に設定できるldSamps [いくつかのインデックス] =サンプル。このようにして、取得した値に一度に1つの構造体を設定し、ldSamps配列の構造体へのインデックスを維持し、プロットと測定のサンプル値にアクセスできるようになると考えています。これは正しいと思いますか、何か不足していますか? –

0

4つの新しいアレイがインスタンスごとに作成され、アレイの内容がRAMに散らばっているので遅いネイティブ配列を用いて、溶液、です。現代のプロセッサは、メモリが可能な限りローカライズされているときに最も速く動作します。

[StructLayout(LayoutKind.Sequential)]  
struct Wvsamps 
{ 
    const int Size = 3; 
    public readonly ushort[] wav1; 
    public readonly ushort[] wav2; 
    public readonly ushort[] wav3; 
    public readonly ushort[] wav4; 
    public readonly ushort modes; 
    public readonly uint time; 
    ushort chkSum; 

    public Wvsamps(uint time, ushort modes) 
    { 
     this.time=time; 
     this.modes=modes; 
     this.wav1=new ushort[Size]; 
     this.wav2=new ushort[Size]; 
     this.wav3=new ushort[Size]; 
     this.wav4=new ushort[Size]; 
     this.chkSum=0; 
    } 

    public void CalcChecksum() 
    { 
     this.chkSum=0; 
     for (int i = 0; i<Size; i++) 
     { 
      chkSum=(ushort)((chkSum+wav1[i]+wav2[i]+wav3[i]+wav4[i])%256); 
     } 
    } 

    public ushort Checksum { get { return chkSum; } } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Wvsamps[] ldSamps = new Wvsamps[0x800000];    

     for (int i = 0; i<ldSamps.Length; i++) 
     { 
      // The constructor initializes the arrays also 
      Wvsamps sample=new Wvsamps((uint)i, 1); 

      //wav1 = [1,2,3] 
      sample.wav1[0]=1; 
      sample.wav1[1]=2; 
      sample.wav1[2]=3; 
      //wav2 = [4,5,6] 
      sample.wav2[0]=4; 
      sample.wav2[1]=5; 
      sample.wav2[2]=6; 
      //wav3 = [7,8,9] 
      sample.wav3[0]=7; 
      sample.wav3[1]=8; 
      sample.wav3[2]=9; 
      //wav4 = [10,11,12] 
      sample.wav4[0]=10; 
      sample.wav4[1]=11; 
      sample.wav4[2]=12; 

      sample.CalcChecksum(); 

      // VERY IMPORTANT 
      // Structs needs to be assigned with one statement as a whole 
      ldSamps[i]=sample; 

      // You cannot do this: ldSamps[i].time = 10; 
     } 

     var checksum = ldSamps[1000].Checksum; 
    } 
} 

使用すると、1つの文で値を割り当てることができ、配列の定義にreadonlyを除去することにより、編集1

。ここでもまた、配列の事前割り振りのために、あなたが何をしたいかによって異なります。

[StructLayout(LayoutKind.Sequential)] 
struct Wvsamps 
{ 
    const int Size = 3; 
    public ushort[] wav1; 
    public ushort[] wav2; 
    public ushort[] wav3; 
    public ushort[] wav4; 
    public readonly ushort modes; 
    public readonly uint time; 
    ushort chkSum; 

    public Wvsamps(uint time, ushort modes) 
    { 
     this.time=time; 
     this.modes=modes; 
     this.wav1=null; 
     this.wav2=null; 
     this.wav3=null; 
     this.wav4=null; 
     this.chkSum=0; 
    } 

 for (int i = 0; i<ldSamps.Length; i++) 
     { 
      Wvsamps sample = new Wvsamps((uint)i, 1); 
      sample.wav1=new ushort[] { 1, 2, 3 }; 
      sample.wav2=new ushort[] { 4, 5, 6 }; 
      sample.wav3=new ushort[] { 7, 8, 9 }; 
      sample.wav4=new ushort[] { 10, 11, 12 }; 

     } 
1

簡単な方法は、すべての構造体の内部で配列を使用することではなく、(wav11、wav12、wav13、wav21 ...)に対応する変数を宣言していない、かもしれません。

[StructLayout(LayoutKind.Sequential)] 
[ImmutableObject(true)] 
public struct Wvsamps 
{ 
    const int Size = 3; 
    public readonly ushort wav11, wav12, wav13; 
    public readonly ushort wav21, wav22, wav23; 
    public readonly ushort wav31, wav32, wav33; 
    public readonly ushort wav41, wav42, wav43; 
    public readonly ushort modes; 
    public readonly uint time; 
    public readonly ushort chkSum; 

    public Wvsamps(uint time, ushort modes, 
     ushort wav11, ushort wav12, ushort wav13, 
     ushort wav21, ushort wav22, ushort wav23, 
     ushort wav31, ushort wav32, ushort wav33, 
     ushort wav41, ushort wav42, ushort wav43, 
     ushort chkSum) 
    { 
     this.time=time; 
     this.modes=modes; 
     this.wav11=wav11; 
     this.wav12=wav12; 
     this.wav13=wav13; 
     this.wav21=wav21; 
     this.wav22=wav22; 
     this.wav23=wav23; 
     this.wav31=wav31; 
     this.wav32=wav32; 
     this.wav33=wav33; 
     this.wav41=wav41; 
     this.wav42=wav42; 
     this.wav43=wav43; 
     this.chkSum=chkSum; 
    } 

} 

public class Samples 
{ 
    public const int Size = 0x800000; 

    readonly Wvsamps[] sample1, sample2, sample3; 

    public Samples() 
    { 
     sample1=new Wvsamps[Size]; 
     sample2=new Wvsamps[Size]; 
     sample3=new Wvsamps[Size]; 
    } 

    public Wvsamps[] Sample1 { get { return sample1; } } 
    public Wvsamps[] Sample2 { get { return sample2; } } 
    public Wvsamps[] Sample3 { get { return sample3; } } 
} 


class Program 
{ 
    static void Main(string[] args) 
    { 
     Samples data = new Samples(); 

     for (int i = 0; i<Samples.Size; i++) 
     { 
      data.Sample1[i]=new Wvsamps((uint)i, 1, 
       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 
       78); 
      // Similarly data.Sample2[i]= ... 
     } 
    } 
} 
+0

私はこれを熟考していましたが、C++のようにあまりエレガントではないように思えました。ループとポインタを使ってWvsamps構造体の配列と構造体内の個々のwav配列のインデックスを作成するのは簡単でした。しかし、C#と一緒になる良い方法かもしれません。 –

+0

あなたはすでに 'wav1'、' wav2'などで分割された配列を持っています。私は本当にあなたが何時に取得する情報に依存します。なぜなら、一度に構造体を初期化し、後でそれに。 質問を編集して、メモリに記録する方法を最適に判断するために、X秒ごとにどのような情報を得るかを例で示すことをお勧めします。 – ja72

+0

オリジナルの投稿を更新してより多くの情報を追加しました。理想的には、Wvsamps構造体のldSamps配列全体が0に初期化されます。1/secで32byteのネットワークパケットを受け取ると、Wvsamps構造体に書き込む必要があり、次のWvsamps構造体を指すようにインデックスldSampsを作成して、そこ。このようにしてWvsamps構造体の0x40000分を累積し、波形プロットと測定のためのサンプルを取得できるようにしたいと思います。 –