問題は、c# プログラムで c++ 構造を使用しようとしていることです。
メールスロットを使用してユーザーインターフェイスと通信していますが、複雑さと古さのためにこれを行う方法は他になく、世界中の 1000 台以上のマシンで実行されています。
私たちの構造は次のようになります
// Message data
typedef struct _t_messageData
{
t_messageHeader header;
t_messageBody body;
t_messageParameter parameter;
} t_messageData;
typedef struct _t_messageHeader
{
UCHAR stx;
UCHAR packetType;
USHORT packetCount;
USHORT checksum;
UCHAR sourceAddress;
USHORT sourcePID;
UCHAR destinationAddress;
USHORT destinationPID;
UCHAR destinationNet;
USHORT packetSequenceNumber;
USHORT packetID;
} t_messageHeader;
// Message body
typedef struct _t_messageBody
{
char order[4];
USHORT module;
USHORT station;
USHORT part;
USHORT position;
} t_messageBody;
// Message parameter
typedef union _t_messageParameter
{
t_internalProcessData internalProcess;
char data[PACKET_DATA_SIZE];
} t_messageParameter;
typedef struct _t_internalProcessData
{
USHORT command;
UCHAR data[PACKET_DATA_SIZE-2];
} t_internalProcessData;
C# では、すべてのサイズがこれらの値によって固定されます。
public const int PACKET_HEADER_SIZE = 17;
public const int PACKET_BODY_SIZE = 12;
public const int PACKET_COMPLETE_SIZE = 4204;
public const int PACKET_DATA_SIZE = PACKET_DATA_SIZE = 4175;
問題はヘッダーやボディではなく、管理が非常に簡単でした。問題は労働組合です。
class MailslotData
{
// Message header
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct SMessageHeader
{
public byte stx;
public byte packetType;
public ushort packetCount;
public ushort checksum;
public byte sourceAddress;
public ushort sourcePID;
public byte destinationAddress;
public ushort destinationPID;
public byte destinationNet;
public ushort packetSequenceNumber;
public ushort packetID;
};
// Message body
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct SMessageBody
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public char[] order;
public ushort placeHolder1; // Old ModuleNbr
public ushort station;
public ushort part;
public ushort placeHolder2; // Old PositionNbr
};
ここで問題が発生します。連合。Fieldoffset を使用すると、同じサイズのバイト配列とストライクの両方を同じ場所に貼り付けることができます。
[StructLayout(LayoutKind.Explicit, Pack = 1)]
public struct SMessageParameter
{
[FieldOffset(0)]
public SInternalProcessData strInternalProcess;
[FieldOffset(0)]
[MarshalAs(UnmanagedType.ByValArray, SizeConst = PACKET_DATA_SIZE)]
public byte[] data;
};
このように定義すると、CalculateChecksum() で ArgumentException が発生します。私は構造体を new で宣言し、ここに見られるように SInternalProcess のみを使用します。
public void CreateInternalProcessMessage(ushort station, ushort part, ushort command)
{
CreateMessageHeader(PACKETTYPE_SINGLE_PACKET, ADDRESS_USERINT, PID_USERINT, DESTINATIONNET_USERINT, 0);
CreateMessageBody (INTERNAL_PROCESS_MESSAGE.ToCharArray(), station, part);
messageData.parameter.strInternalProcess.command = command;
messageData.header.packetCount += (ushort)Marshal.SizeOf (messageData.parameter.strInternalProcess.command);
messageData.parameter.strInternalProcess.data = new byte[PACKET_DATA_SIZE - 2];
messageData.parameter.strInternalProcess.data[0] = (byte)ETX;
messageData.header.packetCount += 1;
CalculateChecksum();
}
CalculateChecksum() では、ArgumentException {「埋め込み配列インスタンスの長さがレイアウトで宣言された長さと一致しないため、型をマーシャリングできませんでした。」} を取得します。
ここの画像で見ることができます。
//これは写真があったはずの部分ですが、私には十分な評判がありません. だから私はそれを書き留めなければなりません。:-(私のrepuが10に達したら、できるだけ早く投稿します。
unsafe void CalculateChecksum()
{
int i = 0;
ushort checksum = 0;
i = Marshal.SizeOf(messageData);
i = sizeof(ushort);
byte[] byteArray = new byte[Marshal.SizeOf(messageData)];
fixed (byte* pArray = byteArray)Marshal.StructureToPtr(messageData, new IntPtr (pArray), false);
// Calculate the checksum
messageData.header.checksum = 0;
for (byte u = 0; u < messageData.header.packetCount; u++)
checksum += byteArray[u];
messageData.header.checksum = checksum;
}
*messageData.parameter.data -> 0x00cc1bfc および *messageData.parameter.strInternalProcess.data -> 0x00cc1bfc
両方のデータ配列が同じ位置を指していますが、これは間違っています。ushort コマンドのために、少なくとも 2 バイトのオフセットが必要です。
私のbyte [] byteArrayは4204です
それで、もっとたくさん読んで自分で理解しようとした後、2つの可能な解決策を見つけました。しかし、それぞれのソリューションには、自分では解決できない問題があります。
まず第一に、私が今まで行ってきたことすべてに何か間違ったことをしているのですか、それとも私が投稿したコードに対する簡単な解決策がありますか?
だから今、私が考えた可能な解決策にたどり着きますが、この投稿の下に個別に投稿します.
ご助力いただきありがとうございます。私はこの時点で1週間以上立ち往生しており、他に試すことが何もないので、すべての回答に感謝します。