Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: C++/CLR Как передать структуру в функцию, ожидающую массив байт  (Прочитано 2932 раз)
0 Пользователей и 1 Гость смотрят эту тему.
jur
Помогающий

lt
Offline Offline

« : 20-05-2024 11:23 » 

Привет!

Понадобилось мне поработать с Cypress USB в программе на C++/CLR. Мое устройство выполнено на микросхеме CY7C68013A. Это микроконтроллер USB 2.0. Для общения с ним используется канал управления (EP2 на вывод, EP4 на ввод). Передача данных управления производится через специальную структуру:
Код:
#ifndef __TYPES
  #define __TYPES
  typedef unsigned char  byte;
  typedef unsigned short word;
#endif

#define SCUSB_CONTROL_STRUCT_DATA_LEN           (512-4)

#pragma pack(push,1)
typedef struct {
  byte cmd;     // SCUSB I/O command code
  byte toggle;  // Free running counter for proper data answer
  word len;     // Data size in bytes
  byte dat[SCUSB_CONTROL_STRUCT_DATA_LEN];
} SCUSB_CONTROL_STRUCT;
#pragma pack(pop)

SCUSB_CONTROL_STRUCT cs;

В программе на C++ (обычном, не управляемом) никаких проблем:
Код:
pControlOutEndpt->XferData((PUCHAR)&cs, sizeof(cs));

А в программе на C++/CLR это выглядит по другому.
Функция передачи/приема данных по USB выглядит так:
Код:
public : virtual bool XferData(array<unsigned char>^ buf, int len) new
    Member of CyUSB::CyUSBEndPoint

Как сделать такую передачу в программе C++/CLR?

Разнообразные попытки вызывают ошибки:
Код:
  ScusbControlOutEndPt->XferData(array<System::Byte>^cs, sizeof(SCUSB_CONTROL_STRUCT));
или
  array<System::Byte>^ bOutbuf = gcnew (cs);
  ScusbControlOutEndPt->XferData(bOutbuf, sizeof(SCUSB_CONTROL_STRUCT));
и другое в этом роде

Помогите, пожалуйста!
Записан

MPEG-4 - в массы!
darkelf
Молодой специалист

de
Offline Offline

« Ответ #1 : 24-05-2024 13:03 » 

Какие именно сообщения об ошибках выдаются?

Почему Вы пытаетесь привести к array<System::Byte>^, тогда как в функции требуют array<unsigned char>^ ?

Возможно в вызове
Код: (C++)
ScusbControlOutEndPt->XferData(array<System::Byte>^cs, sizeof(SCUSB_CONTROL_STRUCT));

не хватает "&"? т.е. должно быть что-то типа

Код: (C++)
ScusbControlOutEndPt->XferData(array<System::Byte>^&cs, sizeof(SCUSB_CONTROL_STRUCT));

Из этого Вам ничего не подходит?
Записан
jur
Помогающий

lt
Offline Offline

« Ответ #2 : 24-05-2024 19:51 » 

Большое спасибо за помощь!

Буду разбираться. Имеется пара вариантов - пробую. Вроде что-то получается.
Наверное мой опыт может пригодиться другим новичкам. Опишу найденное решение.
Записан

MPEG-4 - в массы!
jur
Помогающий

lt
Offline Offline

« Ответ #3 : 25-05-2024 20:38 » new

После смогочисленных проб сделал следующее (static потому, что используется только в текущем файле).
Код:
static void copy_struct_to_array(array<unsigned char>^ buf, SCUSB_CONTROL_STRUCT* cs)
{
  pin_ptr<byte> p = &buf[0];
  byte* arr = p;
  arr[0] = cs->cmd;
  arr[1] = cs->toggle;
  *(word *)&arr[2] = cs->len;
  for ( int i = 0; i < SCUSB_CONTROL_STRUCT_DATA_LEN; i++ ) {
    arr[i + 4] = cs->dat[i];
  }
}
static void copy_array_to_struct(array<unsigned char>^ buf, SCUSB_CONTROL_STRUCT* cs)
{
  pin_ptr<byte> p = &buf[0];
  byte* arr  = p;
  cs->cmd    = arr[0];
  cs->toggle = arr[1];
  cs->len = *(word *)&arr[2];
  for ( int i = 0; i < SCUSB_CONTROL_STRUCT_DATA_LEN; i++ ) {
    cs->dat[i] = arr[i + 4];
  }
}

 Т.е. эти две функции позволяют считывать и записывать содержимое неуправляемой структуры в управляемый массив и обратно. Естественно, что нужно предварительно создать массив необходимого размера (для уверенности добавить Resize при копировании структуры в массив и т.п. проверки).
Таким образом моя задача решается без излишних сложностей.
Код проверен на "железе", работает нормально, именно так, как и требуется.

Как используется.
Код:
int MyForm::USB_ControlOut(SCUSB_CONTROL_STRUCT* cs, int iTimout)
{
  int error = SLE901ERR_OK;  // 0 is OK

  if( !ScusbControlOutEndPt ) { return SLE901ERR_CONTROL_OUT_ENDPOINT_NOT_EXIST; }

  // Check for USB 2.0
  int data_len = sizeof(SCUSB_CONTROL_STRUCT);
  if ( ScusbControlOutEndPt->MaxPktSize != data_len ) {
    System::Windows::Forms::MessageBox::Show("Error");
    return SLE901ERR_CONTROL_OUT_ENDPOINT_NOT_EXIST;
  }
  if ( cs->len > SCUSB_CONTROL_STRUCT_DATA_LEN ) // Prevent error
    cs->len = SCUSB_CONTROL_STRUCT_DATA_LEN;
  ScusbControlOutEndPt->TimeOut = iTimout;
  array<unsigned char, 1>^ buf = gcnew array<unsigned char>(data_len);
  copy_struct_to_array(buf, cs);
  if ( ScusbControlOutEndPt->XferData(buf, data_len) ) {
    Status->Text = "USB_ControlOut OK";
  }
  else {
    error = SLE901ERR_CONTROL_OUT_TRANSFER_FAILED;
  }
  return error;
}

Всем спасибо!
« Последнее редактирование: 25-05-2024 20:47 от jur » Записан

MPEG-4 - в массы!
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines