2012-01-24 18 views
1

我有一箇舊的客戶端應用程序使用VC 6.0 dll寫入命名管道,並且我被要求編寫一個C#應用程序來讀取命名管道並處理請求。我能夠接收字節數組中的數據,但無法使管道中的數據與我在C#中定義的結構相匹配。讀取命名管道從VC++ 6.0 dll發送到c#嵌入式結構中的數據

老C結構

typedef struct 
{ 
    WORD WtYPE; 
    AB objEmbededStruct1; 
    BB objEmbededStruct2; 
    char szString[13]; 
    union 
    { 
    char szString1[25]; 
    char szSTring2[45]; 
    char szString3[134]; 
    } 
    BOOL bExist; 
} myStruct1; 

typedef struct 
{ 
    char szThisString1[2]; 
    int iFlag1; 
    char szThisString2[11]; 


}AB; 

typedef struct 
{ 
    HANDLE hEvents[2]; 
    DWORD dw; 
    int ithisFlag; 


}BB; 

我試圖解析字節數組,但數據是不是在那裏我希望它是。例如,第一個嵌入式結構(AB)中的第一個字符串從字節[4]開始,而不是字節[2],因爲一個字映射到一個無符號的int16。然後,AB結構中的第一個整數從字節[8]開始,而不是字節[6]。那麼,是否有更高效的方式從管道檢索數據並將其放入結構中,或者按字節解析正確的方式?如果解析字節是應該如何完成的,那麼當我嘗試映射數據的位置時,我會丟失什麼?

感謝

+1

我認爲你有一個對齊問題。您可以使用SizeOf來進一步分析問題。 Google for C#結構對齊。 –

+0

優秀!謝謝,讓我到這個鏈接:http://www.developerfusion.com/article/84519/mastering-structs-in-c/,它解釋了所有以及如何從命名管道獲取流數據到結構! – ERukes

+1

好的,你可以在這裏發佈你的解決方案作爲答案。我認爲這需要一兩天才能接受你的答案。 –

回答

0

從LU RD的建議後,我能一起把這個解決方案:VC 6結構的

定義:

typedef struct 
{ 
WORD WtYPE; 
AB objEmbededStruct1; 
BB objEmbededStruct2; 
char szString[13]; 
union 
    { 
    char szString1[25]; 
    char szSTring2[45]; 
    char szString3[134]; 
    } 
BOOL bExist; 
} myStruct1; 

typedef struct 
{ 
char szThisString1[2]; 
int iFlag1; 
char szThisString2[11]; 
}AB; 

typedef struct 
{ 
HANDLE hEvents[2]; 
DWORD dw; 
int ithisFlag; 
}BB; 

我需要using語句到c#代碼:

using System.Runtime.InteropServices; 

c#中的結構定義如下所示:

 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
    public struct RM_CLIENT_DATA 
    { 
     public UInt16 wtype; 
     AB objEmbededStruct1; 
     BB objEmbededStruct2; 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 13)] 
     char[] szString; 
     public Data objMyUnion //this is the structure substituted for the union 
     public int bExist; 
} 


//Union struct 

[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)] 
    public struct Data 
    { 
     [MarshalAs(UnmanagedType.ByValArray, SizeConst = FILE_NAME_LENGTH + 1)] 
     [FieldOffset(0)] 
     public char[] szString1 
     [MarshalAs(UnmanagedType.ByValArray, SizeConst = DOCS_LEN + 1)] 
     [FieldOffset(0)] 
     public char[] szString2; 
     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 134)] 
     [FieldOffset(0)] 
     public char[] szString3; 
    } 

[structLayout(LayoutKind.Sequential, charset = charSet.Ansi)] 
public struct AB 
{ 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] 
     char[] szThisString1; 
    int IFlag1; 
     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] 
    char[] szThisString2; 

} 


[structLayout(LayoutKind.Sequential, charset = charSet.Ansi)] 
public struct BB 
{ 

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] 
     public UInt32[] hEvents; 
     public UInt32 dw; 
     public int ithisFlag; 

} 

的代碼從命名管道拉流引入該結構是這樣的:

 const int BUFFER_SIZE=4096; 
    byte[] typeData = new byte[BUFFER_SIZE]; 
    int iMaxData = ioStream.Read(typeData, 0, BUFFER_SIZE); 


    GCHandle objHandle = new GCHandle(); 

    iMaxData = ioStream.Read(typeData, 0, BUFFER_SIZE); //read the stream 
    try 
      { 

       objHandle = GCHandle.Alloc(typeData, GCHandleType.Pinned); 
       objData = (RM_CLIENT_DATA)Marshal.PtrToStructure(objHandle. 
          AddrOfPinnedObject(),typeof(RM_CLIENT_DATA)); 
      } 
      catch (Exception ex) 
      { 
       ErrorCode = -6; 
       ErrorMessage = string.Format("ReadMessageToGenericStruct: Error: {0} 
        attempting to move data into RM_CLIENT_DATA struct.", ex.Message); 

       return bResult; 
      } 
      finally 
      { 
       objHandle.Free(); 
      } 

在結構使用的char []的,我使用: 串myWorkString =新字符串(objData.szString);

將數據返回到管道 - 我逆轉的過程:

//get the size of the filled structure 
int iStructSize = Marshal.SizeOf(objData); 

//allocate the byte array to write the structure into 
byte[] outBuffer = new byte[ iStructSize]; 

//create the GCHandle variable 
GCHanlde objHandle = new GCHandle(); 

try{ 
    //allocate a handle for the byte array 
    objHandle = GCHandle.Alloc(outBuffer, GCHandleType.Pinned); 

    //move your data to the byte array 
    Marshal.StructureToPtr(objData, objHandle.AddrOfPinnedObject(), false); 

} 
catch (Execeptiion ex) 
{ 
    //write error message here 
} 
finally 
{ 
    //free the handle 
    objHandle.Free(); 
} 


//write the byte array to the stream 
try 
{ 
    ioStream.Write(outBuffer, 0, iStructSize); 

} 
catch (Exception ex) 
{ 
    //write error message here 
} 

ioStream.Flush(); 
ioStream.Close(); 

下面的鏈接是一個很大的幫助,這要歸功於作者的! Mastering c# structs