Чтение именованных каналов данных, отправленных из DLL VC ++ 6.0 во встроенные структуры в c # - PullRequest
1 голос
/ 25 января 2012

У меня есть старое клиентское приложение, которое пишет в именованные каналы с использованием dll VC 6.0, и меня попросили написать приложение C # для чтения именованного канала и обработки запроса.Я могу получить данные в байтовом массиве, но не могу получить данные в конвейере для сопоставления со структурами, которые я определил в C #.

old C struct

  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], поскольку слово отображается в беззнаковое целое 16.Тогда первое целое число в структуре AB начинается с байта [8], а не с байта [6].Итак, есть ли более эффективный способ извлечь данные из канала и поместить их в структуру, или правильный анализ выполняется байтами?Если синтаксический анализ байтов - то, как это должно быть сделано, то чего мне не хватает при попытке сопоставить, где должны быть данные?

Спасибо

1 Ответ

0 голосов
/ 27 января 2012

после предложения от 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;

Мне нужно было использование оператора в коде 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 [] в структуре, я использовал: string myWorkString = new string (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();

следующая ссылка очень помогла, спасибо этому автору! Освоение структур c #

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...