-2

問題は、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週間以上立ち往生しており、他に試すことが何もないので、すべての回答に感謝します。

4

2 に答える 2

0

タイプ 'GettingStartedClient.MailslotData+SMessageData' は、管理されていない構造としてマーシャリングできません。意味のあるサイズまたはオフセットを計算できません。

だから私は [MarshalAs(UnmanagedType.

今、私はその理由を知っています。その背景を理解することで、すべてが明らかになります。固定配列をマッシュアップしようとしていました。マシェルが行うことは、構造を再配置して、見た目を決定したように見せることです。これは mashal コマンドでは固定配列では実行できません。

したがって、解決策は非常に簡単でした。マシャリングを取り除き、ほら。それはすべて正常に動作します。

[StructLayout(LayoutKind.Explicit, Size = PACKET_DATA_SIZE, Pack = 1)]
public unsafe struct SInternalProcessData
{
    [FieldOffset(0)]
    public ushort command;
    [FieldOffset(1)]
    public fixed byte data[PACKET_DATA_SIZE - 2];
};

[StructLayout(LayoutKind.Explicit, Size = PACKET_DATA_SIZE, Pack = 1)]
public unsafe struct SMessageParameter
{
    [FieldOffset(0)]
    public SInternalProcessData strInternalProcess;
    [FieldOffset(0)]
    public fixed byte data[PACKET_DATA_SIZE];
};
于 2012-11-29T13:29:14.343 に答える
0

問題の可能な解決策は、自分では解決できない新しい問題です。

以下の定義を変更しました。

    public byte[] data;   
    to look as followed
    public fixed byte data[PACKET_DATA_SIZE];

ここでは、全体の変更を確認できます

public unsafe struct SInternalProcessData
{
    public ushort command;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = PACKET_DATA_SIZE - 2)]
    public fixed byte data[PACKET_DATA_SIZE - 2];
};

[StructLayout(LayoutKind.Explicit, Pack = 1)]
public unsafe struct SMessageParameter
{
    [FieldOffset(0)]
    public SInternalProcessData strInternalProcess;
    [FieldOffset(0)]
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = PACKET_DATA_SIZE)]
    public fixed byte data[PACKET_DATA_SIZE];
};


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_COMPLETE_SIZE - PACKET_HEADER_SIZE - PACKET_BODY_SIZE;
//value PACKET_DATA_SIZE = 4175 

これにより、両方のデータ配列が同じ場所を指しているという問題が修正されます。写真でわかるように。しかし、それは新たな問題を引き起こします。

ArgumentException

Type 'GettingStartedClient.MailslotData+SMessageData' cannot 
be marshaled as an unmanaged structure; no meaningful size or offset can be computed.

だから私は [MarshalAs(UnmanagedType.

構造体 Marshal.SizeOf(messageData.parameter.data) のサブセットを使用してすべての設定をテストしました

だからここに私が助けを必要とする私の問題があります。

于 2012-11-29T10:24:57.703 に答える