Я пытаюсь построить и написать бинарный запрос, и у меня есть вопрос типа «это возможно». Для меня может быть важно упомянуть, что получатель запроса не знает о структуре данных, которую я включил ниже, он просто ожидает последовательность байтов, но использование структуры кажется удобным способом подготовки частей запроса, тогда напишите их легко.
Писать верхний и нижний колонтитулы хорошо, так как они имеют фиксированный размер, но я сталкиваюсь с проблемами со структурой «Детали» из-за вектора. На данный момент я пишу в файл, чтобы я мог проверить запрос, чтобы специфицировать, но намерение состоит в том, чтобы написать в ПЛК с использованием последовательного порта boost asio в конце концов
Я могу использовать синтаксис так, чтобы написать структуру, но она записывает адреса указателя, а не значения, когда он попадает в вектор
myFile.write((char*) &myDataRequest, drSize);
Я могу использовать этот синтаксис для написания вектора самостоятельно, но я должен включить индексатор в 0, чтобы записать значения
myFile.write((char*) &myVector[0], vectorSize);
Есть ли элегантный способ написать двоичную структуру, содержащую вектор (или другую подходящую коллекцию), делая это за один раз? Скажем, например, если я объявил вектор по-другому, или я смирился с выполнением нескольких записей для содержимого внутри структуры. Если я заменю вектор массивом, я могу отправить структуру за один раз (без необходимости включать какой-либо индексатор), но я не знаю требуемый размер до времени выполнения, поэтому я не думаю, что он подходит.
Моя структура
struct Header
{ ... };
struct Details
{
std::vector<DataRequest> DRList;
};
struct DataRequest
{
short numAddresses; // Number of operands to be read Bytes 0-1
unsigned char operandType; // Byte 2
unsigned char Reserved1; //Should be 0xFF Byte 3
std::vector<short> addressList; // either, starting address (for sequence), or a list of addresses (for non-sequential)
};
struct Footer
{ ... };
Это невозможно, потому что std::vector
Объект на самом деле не содержит массив, а указатель на блок памяти. Тем не менее, я испытываю соблазн утверждать, что возможность писать необработанную структуру подобным образом нежелательна:
Я считаю, что, рассматривая структуру как блок памяти, вы можете в конечном итоге посылать байты заполнения, я не думаю, что это желательно.
В зависимости от того, что вы пишете, вы можете обнаружить, что записи в любом случае буферизуются, поэтому множественные вызовы записи на самом деле не менее эффективны.
Скорее всего, вы хотите сделать что-то с полями, отправляемыми. В частности, с числовыми значениями, которые вы отправляете. Это требует применения порядка байтов, с которым согласны обе стороны передачи. Чтобы быть переносимым, вы должны точно преобразовать порядок байтов, чтобы убедиться, что ваше программное обеспечение переносимо (если это требуется).
Короче говоря, я подозреваю, что написание каждого поля одно за другим не менее эффективно, но и более правильно.
Это не очень хорошая стратегия, поскольку, даже если вы можете сделать это, вы копируете содержимое памяти прямо в файл. Если вы измените архитектуру / процессор, ваш клиент получит другие данные. Если вы напишите метод, принимающий вашу структуру и имя файла, который будет записывать значения структур по отдельности и перебирать вектор, записывая его содержимое, вы будете иметь полный контроль над двоичным форматом, ожидаемым вашим клиентом, и не зависят от текущей памяти компилятора. представление.
Если вы хотите удобство маршаллинга / демаршаллинга, вам стоит взглянуть на повышение :: сериализации библиотека. Они предлагают бинарный архив (помимо текста и xml), но он имеет свой собственный формат (например, у него есть номер версии, какая библиотека сериализации использовалась для выгрузки данных), так что это, вероятно, не то, что хочет ваш клиент.
Какой именно формат ожидается на другом конце? Вы должны написать
это, период. Вы не можете просто написать произвольные байты. Вероятность
что просто написание std::vector
как вы делаете, работа о
как можно ближе к 0, как вы можете получить. Но вероятность того, что написание
struct
только с int
будет работать еще менее 50%. Если другой
сторона ожидает определенную последовательность байтов, то вы должны написать
эта последовательность, побайтово Написать int
Например, вы должны
по-прежнему записывать четыре (или что требует протокол) байта, что-то
лайк:
byte[0] = (value >> 24) & 0xFF;
byte[1] = (value >> 16) & 0xFF;
byte[2] = (value >> 8) & 0xFF;
byte[3] = (value ) & 0xFF;
(Даже здесь, я полагаю, что ваше внутреннее представление отрицательного
номера соответствуют номерам протокола. Обычно бывает, но не так
всегда.)
Обычно, конечно, вы строите свой буфер в std::vector<char>
,
а потом написать &buffer[0], buffer.size()
, (Тот факт, что вам нужно
reinterpret_cast
указатель буфера должен сигнализировать, что ваш
подход неправильный.)