@Ultrakayo

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

C++言語で作成した構造体をC#に移植したい

C++
struct SYSINFO {
unsigned short id;
unsigned short cnt;
unsigned short disp;
unsigned short cf;
unsigned short rsv1[4];
unsigned short no[4];
unsigned char sel[4];
unsigned char type[4];
}
main.h
class TSample: public TForm
{
public: SYSINFO sysinfo[64];
main.cpp
TSample *sample;

art.cpp
sample->sysinf[10].id=0x890;
sample->sysinf[10].sel[5]=4;
みたい 使い方します。
 C# でも 同じような方法が できないでしょうか?

例 
work.cs
public class SysInfoClass{
public UInt16 id;
public UInt16 cnt;
public UInt16 disp;
public UInt16 cf;
public UInt16[] rsv1 = new UInt16[4];
public UInt16[] no =new UInt16[4];
public Byte[] sel= new Byte[4]
public Byte[] type=new Byte[4];
}

main.cs
public static SysInfoClass[] sinfo = new SysInfoClass[64];

sinfo[0].id = 0x980;
sinfo[0].rsv1[0] = 1; <<<< ここで 実行エラー

いろいろ 試しましたが
 うまくいきません。
ご教示願います。
※ 一次配列なら うまく動作しますが
  二次配列は どうも コンパイルOKでも
  DEBUGで エラー 
追補:
work.cs
最初から 二次配列にすれば問題ないようですが
public class SysInfoClass{
public UInt16[] id =new UInt16[64];
public UInt16[] cnt=new UInt16[64];
public UInt16[] disp=new UInt16[64];
public UInt16[] cf =new UInt16[64];
public UInt16[,] rsv1 = new UInt16[64,4];
public UInt16[,] no =new UInt16[64,4];
public Byte[,] sel= new Byte[64,4]
public Byte[.] type=new Byte[64,4];
}
この場合
 syinfo.id[0]=0x980;
 syinfo.rev1[0]=1;
のようになってしまいます

sinfo[0].id = 0x980;
sinfo[0].rsv1[0]=1;
プログラムの都合上
sinfo[0].id = 0x980;
sinfo[0].rsv1[0]=1;
 こういう使い方をしたいのです
 

0 likes

4Answer

構造体(クラス)を配列のように扱うのであればインデックスプロパティを定義しましょう
グローバルなインスタンスとして扱えるようにする場合は静的メンバを用意します
以下のプログラムは.net9.0に準拠しています
各宣言は使用するバージョンに合わせて適宜書き換えて下さい

using System;
using System.Linq;
using static Builder;

public struct SysInfoClass{
    public SysInfoClass(){}
	public UInt16 id;
	public UInt16 cnt;
	public UInt16 disp;
	public UInt16 cf;
	public UInt16[] rsv1 =new UInt16[4].Create();
	public UInt16[] no =new UInt16[4].Create();
	public Byte[] sel= new Byte[4].Create();
	public Byte[] type=new Byte[4].Create();
}

public struct TSample{
	public TSample(){}
	private readonly SysInfoClass[] sysinfo=new SysInfoClass[64].Create();
	public SysInfoClass this[int i]=>sysinfo[i];
}

public static class Builder{
	public static readonly TSample ts=CreateTSample();
	static TSample CreateTSample()=>new();
	
    public static T[] Create<T>(this T[] arr) where T:new()
		=>arr.Select(x=>x=new()).ToArray();
}

これにより、TSampleを通じて以下のようにアクセスできます

public class Program
{
	public static void Main()
	{
		ts[0].sel[1]=1;
		Console.WriteLine(ts[0].sel[1]);
	}
}
1
1Like

Comments

  1. @Ultrakayo

    Questioner

    ありがとうございます。参考にさせていただきます。

public static SysInfoClass[] sinfo = new SysInfoClass[64];
sinfo[0].id = 0x980;
sinfo[0].rsv1[0] = 1; <<<< ここで 実行エラー

エラーが出ているのはそこではなく sinfo[0].id = 0x980; の時点です。 new SysInfoClass[64] で作った配列はすべての要素が null になるため、 sinfo[0].id = 0x980; は配列0番目の null に対して id フィールドに代入しようとしてエラーになります。

以下のように配列を初期化してください。

public static SysInfoClass[] sinfo = new SysInfoClass[64];
for (int i = 0; i < sinfo.Length; i++)
{
    sinfo[i] = new SysInfoClass();
}

なお追補についてですが、そこを二次元配列にしても元々のエラーが解消することはないはずです。何か勘違いしているのでは。

0Like

Comments

  1. 何が言いたいかよく分かりません。元の質問と全然違うコードのようですが。

    また Program.cs に var chinfo = new ChargeInfo[4]; と書いても chinfo は他のファイルから参照できないので、それが実際のコードというのも謎です。動いているコードがあるなら改変せずに貼ってください。

  2. 「色々 試行錯誤してたら 元のファイルが無くなり ダメなファイルですが」のコメントについてですが、

    chinfo[0].chk[0] = 1; //これは ダメ
    二次配列の初期化が 抜けていると

    これでエラーが出るのは二次元配列の初期化が抜けているのではなくて(そもそもそのコードの中に二次元配列は出てきません) static である chk フィールドに代入しようとしているからです。

    その次、「追補」のコメントについてですが、コンパイルが通るなら何が問題なのですか?コードがまた大きく変わっていて前の質問とのつながりが分からず、コードで何が達成したいのかも読み取れないので、特にアドバイスできません。

    その次のコメントについてですが、

    こういう風にすれば どこからでも アクセスできますよと
    しかし  構造体には 二次元配列が 含まれていなかったので
    いろいろ作り変えたのが 最初の文です。

    前のコメントでも何度か二次元配列の話が出てきていましたが、移植元の C++ の構造体に二次元配列が含まれていないのに、 C# で二次元配列を使おうとしているのはなぜですか?

  3. 話をするたびに出てくるコードや起きている問題が変わると回答する側としても困るので、やりたいことを明確にし、実際のコードを確定してから質問し直してください。

  4. @Ultrakayo

    Questioner

    了解しました。 ありがとうございました。

This answer has been deleted for violation of our Terms of Service.

そもそもC#上で固定長配列を持つ構造体を扱うのは面倒なので、C#でやるならクラスやList等を使ったり、C#のやり方でコーディングした方がいいです。
無理矢理C++的な事をするなら、最初からC++で組んだ方がよいと思います。

0Like

Your answer might help someone💌