2012-11-29 3 views
-2

문제는 C# programm에서 C++ 구조체를 사용하려고한다는 것입니다.구조체 구조체를 marshal.sizeof와 결합하는 방법 C#/C++

우리는 사용자 인터페이스와 통신하기 위해 메일 슬롯을 사용하고 있으며 복잡성과 수명으로 인해이 작업을 수행 할 수있는 다른 방법이 없으며 전 세계의 1000 대 이상의 컴퓨터에서 실행됩니다.

우리의 구조는 모든 크기는이 값으로 고정 C#에서이

// 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; 

것 같습니다.

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을 사용하면 동일한 크기를 가진 바이트 배열과 struckt를 동일한 위치에 둘 수 있습니다.

[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을 얻습니다. 새로운 구조체를 선언하고 여기서 본 것처럼 SInternalProcess 만 사용합니다. CalculateChecksum() 나는 경우 ArgumentException를 얻을 수 있습니다에서

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(); 
} 

가 { "내장 배열 인스턴스의 길이가 레이아웃에서 선언 된 길이와 일치하지 않기 때문에 유형이 마샬링 할 수 없습니다."}

하는 당신은 할 수 여기에있는 이미지를 참조하십시오.

// 그림이 있었지만 충분한 평판이없는 부분입니다. 그래서 그것을 적어 둡니다. :-(내가 그것을 게시 해 드리겠습니다 것은 최대한 빨리 내 어 Repu은 최대

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; 
} 

enter image description here 10 * messageData.parameter.data -> 0x00cc1bfc 및 * messageData.parameter.strInternalProcess.data - > 적어도 2 바이트 때문에 USHORT 명령 오프셋 0x00cc1bfc 모두 데이터 배열의 잘못 동일한 위치를 가리키는

가되어야한다.

,

내 바이트 [] byteArray는 4204

그래서 더 많이 읽고 나 자신을 이해하려고 시도한 결과 2 가지 가능한 해결책을 발견했습니다. 그러나 각 솔루션에는 내가 스스로 해결할 수없는 문제가 있습니다.

우선 제가 지금까지 해본 모든 일에서 뭔가 잘못하고 있습니다. 아니면 내가 게시 한 코드에 대한 간단한 해결책이 있습니다.

그럼 이제 가능한 해결책을 찾으러 올 테지만이 게시물 아래에 별도로 게시 할 것입니다.

도움 주셔서 감사합니다. 나는 지금 1 주일 이상이 시점에서 붙어 있고 시도 할 다른 것을 모르기 때문에 모든 대답에 감사를 표했다.

답변

0

문제를 해결할 수있는 새로운 해결책은 스스로 해결할 수없는 문제입니다. 다음은 전체이 내가 같은 위치에서 두 데이터 배열의 가리키는이 문제를 해결

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 

변경 볼 수 있습니다

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

:

나는의 정의를 변경했습니다. 그림에서 알 수 있습니다. 그러나 새로운 문제를 야기합니다.
Type 'GettingStartedClient.MailslotData+SMessageData' cannot 
be marshaled as an unmanaged structure; no meaningful size or offset can be computed. 

ArgumentException

는 그래서 [MarshalAs (UnmanagedType의 설정으로했다.하지만 난 잘 작동 것 구성을 찾을 수 없습니다.

내가로부터 하위 집합으로 모든 설정을 테스트 내 구조 Marshal.SizeOf (messageData.parameter.data) 그래서 여기

내가 몇 가지 도움이 필요 나의 문제입니다.

+0

내 해결책을 찾았습니다. 단어를 삽입하는 방법을 알 자마자이를 공유합니다. –

0

유형 'GettingStartedClient.MailslotData + SMessageData'는 을 관리되지 않는 구조로 정렬 할 수 없습니다. 의미있는 크기 또는 오프셋은 계산할 수 없습니다. .

는 그래서 [MarshalAs (UnmanagedType의 설정으로했다.하지만 난 잘 작동 것 구성을 찾을 수 없습니다.

을 이제 내가 왜. 그래서 배경이 다하게 이해하고 알고 고정 된 배열을 마샬링하려고했습니다. 마셀은 고정 된 배열을 사용하여 마샬 명령이 수행 할 수없는 것처럼 보이도록 구조를 재정렬하는 것입니다.

따라서 솔루션 꽤 쉽습니다. 매셔 링과 보일을 제거하십시오. 모두 정상적으로 작동합니다.

[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]; 
}; 
관련 문제