Logo GenDocs.ru

Поиск по сайту:  

Загрузка...

Лабораторная работа 01. Лабораторная работа 02. Лабораторная работа 03. Лабораторная работа 04 - файл


скачать (180.6 kb.)


Системное программирование.

План лабораторных работ

Для 1 семестра 4 курса ВКИ НГУ.

Издание 07.

Оглавление

Семестровый проект.

Лабораторная работа 01.

Лабораторная работа 02.

Лабораторная работа 03.

Лабораторная работа 04.

Лабораторная работа 05.

Лабораторная работа 06.

Требования к оформлению работ.

Оценивание работ.

Методические рекомендации.

Семестровый проект.

Создать исполняемый файл и dll-библиотеку, которые подключаются к XML-документу с QR-кодами, редактируют его, кодируют и декодируют битмап, опционально передавая его по порту обмена или сети.

Лабораторная работа 01.

Создать исполняемый файл, формирующий и сохраняющий XML-документ со следующей структурой:



















































Количество узлов Bitmap и Row выполнять произвольным.

В узлах Row будет храниться набор из 11 байт в строковом шестнадцатеричном представлении, разделённых одним пробелом



01 02 03 04 05 06 07 08 09 0A FF





Получившийся документ сохранять в папку с исполняемым файлом через CreateFile, или через встроенную в язык обёртку для него (если такая есть).

Язык – произвольный компилируемый.

Лабораторная работа 02.

Создать исполняемый файл, который подключается к созданному в ходе лабораторной работы 01 XML-документу через CreateFile и изменяет один из байтов одного из столбца. Для простоты достаточно принять BitmapN = 1, RowN = 2, байт 3.

Здесь и далее к документу подключаться через WinApi (CreateFile), предусматривать следующее:

в начало документа могут быть добавлены произвольные узлы, в целевой узел может быть добавлены любые атрибуты.

документ может иметь произвольную кодировку (т.е. при обходе игнорировать байты с нулевым значением).

Целевой узел уникален (то есть параметры BitmapN и RowN не повторяются).

Лабораторная работа 03.

Опубликовать интерфейс с методами



BSTR GetVersion(void)

BSTR GetDescription(void)

HRESULT UpdateBitmap(BSTR DocumentLocation, BSTR EncodedBytes)

HRESULT SaveBitmap(BSTR DocumentLocation, int Index)

tagBitmap CreateBitmap(BSTR DocumentLocation)


Методы должны делать следующее:

GetVersion

Возвращает версию.

GetDescription

Возвращает описание. В описании должны быть имя и группа автора, а также текстовое описание того, что делает экземпляр интерфейса.

UpdateBitmap

Обновляет произвольный набор байт. Формат посылки EncodedBytes будет описан ниже

SaveBitmap

Честно сохраняет битмап в формате bmp.

CreateBitmap

Возвращает структуру, являющуюся битмапом (то есть если, например, сохранить её на диск или передать по сети, то на принимающем конце она корректно обработается)

Все методы должны быть опубликованы с соглашением вызова stdcall.

На методы SaveBitmap и CreateBitmap поставить заглушку, остальные – реализовать.

В строке EncodedBytes зашифрован обновлённый набор байт. Старший байт символа равен номеру байта, к-рый надо обновить (счёт ведётся с единицы). Младший байт равен новому значению этого байта. Под «номером байта» подразумевается закодированное значение пикселя, которое помещалось в документ из лабораторной 1. Так, если бы документ состоял из одной строки «00 FF DE», то третьим байтом считался бы не пробел, а значение DE.

Под публикацией и реализацией подразумевается:

1)Создание заголовочного файла, в котором будет описан целевой интерфейс (для случая C++ – абстрактный класс, содержащий только виртуальные методы и не более того)

2)Создание в отдельном модуле класса, реализующего целевой интерфейс.

Под отдельным модулем с классом может подразумеваться связка .h + .cpp

Все возможные исключения должны быть экранированы (try-catch).

Лабораторная работа 04

Реализовать методы SaveBitmap и CreateBitmap из прошлой лабораторной. Метод SaveBitmap должен сохранять честный битмап в формате bmp в папке с XML-документом.

Лабораторная работа 05

Создать связку из исполняемого файла и dll-библиотеки, написанных на разных языках и задействующих интерфейс, созданный в ходе предыдущих двух лабораторных.

Иными словами, требуется


  1. Переделать сделанное в ходе предыдущих работ приложение в dll-библиотеку, сделать функцию(и) экспорта интерфейса, заданного в ходе лабораторной 3, создать приложение, подключающее свежепеределанную dll и задействующее методы означенного интерфейса

ЛИБО

  1. Создать dll-библиотеку, подключить её к созданному в ходе предыдущих работ приложению, в dll-библиотеке создать функцию, которая принимает входным параметром интерфейс, заданный в ходе лабораторной 3, и сохраняет его в качестве глобальной/локальной переменной. Ссылка на интерфейс должна подчищаться после использования.

В качестве «полезной нагрузки» связка exe+dll должна инвертировать цвета битмапа, получаемые из XML-документа.

Здесь и далее, ту часть, которая реализует сделанное в ходе лабораторных 1-4 будем называть «содержимым», а новые дополнения – «обёрткой».

Лабораторная работа 06

В приложении/библиотеке, реализованных на ином языке, нежели результат лабораторных 1-4 («обёртке»), получать количество ядер процессора.

Далее, в «обёртке» же завести число потоков по количеству ядер процессора и выполнять задачу предыдущей лабораторной (т.е. инвертирование цветов) в многопоточном режиме. Количество потоков должно быть равным количеству ядер, приоритеты потоков должны быть одинаковыми, причём менее максимально возможного, объёмы работы должны быть максимально близки друг к другу.

Требования к оформлению работ.

1. Языки и среды.

1.01. Языки должны быть компилируемыми, со статической типизацией, на выбор автора.

1.02. Для разнотипных файлов, общающихся через интерфейсы, языки должны быть разными (любое число не менее 2), не являющихся аналогами по представлению в памяти. То есть связка Java + Kotlin не подойдёт, т.к. оба являются надстройкой над JVM, C + C++ или Delphi + C Builder не подойдёт, т.к. даже не очень близкие к API инструкции идентичны чуть ли не байт в байт. Напротив, связка Java + C#, C# + C++, Lazarus + Kotlin вполне подойдёт.

2. Оформление кода

2.01. В каждом модуле должен стоять комментарий с ФИО и группой автора.

2.02. Каждый метод (функция, процедура) должны иметь комментарий, хотя бы описывающие что этот метод делает. Если существует реализация методов класса, отделённая от их объявления, то комментировать следует реализацию.

2.03. В коде не должно быть «магических констант». Все константы должны быть поименованы.

Примеры:


//неправильно

if (str[counter] == 0009)

{counter++;}

//правильно

const char TabSymbol = 0009; //код символа табуляции

...


if (str[counter] == TabSymbol)

{counter++;}



2.04. Не должно быть двух одноимённых литералов с точностью до регистра и символа подчёркивания

Примеры того, как не надо:



myclass MyClass;

int somevalue, SomeValue, some_value;



2.05. Имена переменных, классов, методов и т.п. должны содержать хотя бы один символ латиницы и не начинаться с символа нижнего подчёркивания

Примеры того, как не надо:



int _SomeValue1;

int __SomeValue2;

int _1;


2.06. Если для методов класса язык позволяет как разделять объявление и реализацию, так и не делать этого, то смешивать эти варианты не следует.

Примеры того, как не надо:



class TMyClass

{

int IncArg(int AValue)



{

return AValue + 1;

}

int DecArg(int AValue)



}

int TMyClass::DecArg(int AValue)

{

return AValue – 1;



}

2.07. То же относится к разделению на декларативную и исполняемую часть (в случае C++ .h и .cpp). Либо всё вместе, либо разделять (и лучше действительно разделять).

2.08 В пределах одного модуля для отступов следует пользоваться либо пробелами, либо табуляцией, но не тем и другим вместе.

4. Структура проекта.

4.01. Однотипные файлы проекта должны быть сгруппированы в одной папке и отделены от остальных. Мешать модули, исполняемый файл, файл проекта и остальное в одну папку нельзя.

4.02. Временные/вспомогательные файлы должны храниться в своих папках.

4.03. Модули должны храниться в собственной папке, не содержащей более ничего (кроме подпапок с другими модулями). Заголовочные файлы и файлы с формами считаются за модули.

4.04. Собираемый файл (исполняемый файл, библиотека, служба) должен находиться в отдельной папке, где нет ничего, кроме файлов, необходимых для работы (файлы настроек, логи и т.п.). Если в этой папке находятся исходники проекта, то они должны быть сгруппированы в одну папку.

4.05. Собираемый файл и файлы проекта должны группироваться так, чтобы вырезанием/копированием/удалением одной папки можно было оставить только файлы, необходимые и достаточные для запуска проекта, либо только файлы, необходимые и достаточные для его сборки.

Пример 1:

Application

Папка с приложением

Source

Units

Папка с модулями

TempFiles

Папка с временными файлами

Resources

Папка с ресурсами

А ещё здесь файлы проекта

Пример 2:



Source

Units

Папка с модулями

TempFiles

Папка с временными файлами

Resources

Папка с ресурсами

Application

Папка с приложением

А ещё здесь файлы проекта

Пример 3:

Application

Source

Units

Папка с модулями

TempFiles

Папка с временными файлами

Resources

Папка с ресурсами

А ещё здесь <В папке Source> файлы проекта

А ещё здесь <В папке Application> файл приложения, логи и прочее

Оценивание работ.

По итогу сданных лабораторных будут использоваться следующие критерии оценки:



Удовлетворительно

Выполненные лабораторные 1-4

Хорошо

Выполненные лабораторные 1-5

Отлично

Выполненные лабораторные 1-6

5. Методические рекомендации по выполнению лабораторных работ:

Для лабораторной работы №1.

XML-документ является обычным текстовым документом, имеющим определённую структуру. Таким образом первая часть задачи состоит в том, чтобы получать строку необходимой формы. Если обучающийся неплохо ориентируется в специфичных приёмах/библиотеках/фреймворках для работы с XML-документами, то для формирования строки может пользоваться ими; в противном случае быстрее и проще будет формировать обычную строковую переменную.

Вторая часть задачи состоит в том, чтобы получить дескриптор файла. Вызов функции CreateFile широко описан в документации MSDN и профильной литературе.

В текущем издании описание параметров функций WinAPI не приводится, оставаясь в качестве самостоятельной работы.

Третья часть состоит в том, чтобы, имея готовый дескриптор файла, с его помощью записать полученную ранее строковую переменную. Это можно сделать, например, функцией WriteFile. В сумме эти шаги позволят сформировать XML-документ заданной структуры.

После того, как документ был сформирован, требуется закрыть его, вызвав функцию CloseHandle.

Для лабораторной работы №2.

Здесь требуется примерно то же самое, только добавляются функции чтения данных из файла и выставления указателя на нужную позицию.

Под указателем здесь подразумевается указатель на ту область памяти, привязанную к файлу, которая будет сейчас прочитана или перезаписана. Он привязан к дескриптору файла и его не следует пытаться получить в явном виде или пытаться работать с ним как с указателем типа Pointer. Это просто позиция для чтения или записи.

К описанным ранее WinAPI-функциям добавятся ReadFile и SetFilePointer.

С помощью ReadFile требуется читать буфер из документа, парсить его, и определять позицию нужного байта. После того, как требуемая позиция найдена, нужно выставить функцией SetFilePointer позицию указателя.

Парсинг строки и вычисление позиции указателя покамест тоже остаётся предметом самостоятельной работы учащегося.

Стоит отметить, что функция записи WriteFile запишет/перепишет данные, находящиеся сразу после указателя, поэтому следует ставить его ровно перед тем байтом, который должен быть перезаписан.

Для лабораторной работы №3.

Как правило, при создании интерфейса создают заголовочный файл, в котором содержится описание интерфейса. Далее создают модуль с классом, реализующим этот интерфейс.

В случае лабораторной №3 строковые параметры передаются посредством COM-строки BSTR. Этот строковый тип определён независимо от языка, компилятора или настроек среды, и поэтому является пригодным для передачи между приложениями/библиотеками/службами, как бы те ни были написаны. В методе GetDescription следует дать словесное описание интерфейса, чтобы посторонний человек мог понять, что происходит внутри интерфейса. Метод GetVersion нужен для того, чтобы разработчик мог, с одной стороны, обновлять реализацию интерфейса, а, с другой стороны, сигнализировать об этом. Как именно обозначать версию – «1», «01», «0.0.0.1», «1.0.0.0» – неважно и остаётся на выбор учащегося, главное, чтобы принятая в первой версии система оставалась одной и той же для версий последующих.

Тип данных HRESULT по представлению в памяти совпадает с обычным 32-битным числом, но заведён специально для того, чтобы помещать в него коды результатов выполнения функций. По своей спецификации, старший бит переменной отведён для успешности или неуспешности выполнения функции; иными словами, для успешных результатов предназначены неотрицательные значения, а для неуспешных – отрицательные. Также существуют правила для использования старших битов переменной, но они регулярно игнорируются, поэтому для базового вхождения достаточно назначать для неуспешных исходов. Стоит отметить 3 константы – S_OK, назначаемая для успешных исходов и численно равную 0, S_FALSE, численно равную 1, и назначаемую для исходов, формально успешных, но выполнивших не то, что подразумевалось, и E_NOTIMPL, численно равную 0x80004001 и предназначенную для вывода информации о том, что процедура/метод не имеют реализации. В частности, заглушка метода SaveBitmap должна возвращать именно её – потому что на третьей лабораторной работе этот метод уже описан, но ещё не имеет реализации. Вообще, при описании констант стоит подтянуть их из комплекта поставки IDE, а не переопределять; численные значения даны здесь просто для справки.

Тип данных Bitmap описан на официальном сайте: https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmap

Функция UpdateBitmap должна была обновлять как XML-документ с представлением битмапа, так и сам битмап, автоматически определяя тип передаваемого ей файла; однако, из-за недостатка учебного времени, достаточно обновлять только XML-документ.

Так как интерфейс разрабатывается «с прицелом» на интеграцию с динамически подключаемыми библиотеками, то входным параметром задаётся также путь до целевого файла. Предполагается, что путь должен быть полным. Если файл не существует, то должна возвращаться отрицательная целочисленная константа, кодирующая собой отсутствие файла. Так же должны обрабатываться другие ошибки валидации, наподобие невозможности получить доступ к файлу. Для случая пустой строки EncodedBytes следует назначить результатом константу S_FALSE, потому что, с одной стороны, никакой ошибки во время выполнения не произошло, а с другой – никакой полезной работы не было выполнено.

Вообще массив данных кодируется строкой именно потому, что с одной стороны ряд языков имеют крайне затруднённую работу с указателями, чтобы передавать указатель на голый массив данных, с другой – специфические реализации динамических массивов, чтобы формировать массив подобным образом. Кодирование строкой является выгодным компромиссом: динамический массив не только однозначно кодируется и декодируется, но и хранится в стандартизированном типе данных

Реализация этого метода весьма похожа на задачу предыдущей лабораторной работы, но с некоторыми значимыми отличиями.

Во-первых, открытие и закрытие дескриптора файла выполняется единоразово в начале и в конце работы. В промежутке циклом выполняется перезапись частей XML-документа. Весьма целесообразно будет предварительно сортировать набор перезаписываемых байт. Например, можно создать структуру, состоящую из двух байт (с порядковым номером и новым значением), а потом создать динамический массив, элементами которого являются экземпляры такой структуры, заполнить его на основе строки EncodedBytes, а после отсортировать его и выбросить дубликаты.

В любом случае, задача будет подобна предыдущей, с той только разницей, что нужно будет обращаться не к номеру строки, а к номеру байта.

Реализация методов SaveBitmap и CreateBitmap будет описана ниже.

Для лабораторной работы №4.

Существует тип данных BMP/Bitmap, структура которого описана, например, здесь (https://ru.wikipedia.org/wiki/BMP). Следует создать реализацию методов SaveBitmap и CreateBitmap, которые будут на основе XML-представления создавать битмап. Сама процедура создания битмапа будет совпадать для обоих методов, но один должен будет возвращать получившуюся структуру, а другой – сохранять на диск.

Сохранение на диск было рассмотрено в ходе лабораторных 1 и 2, то, что в этот раз данные являются не строкой, а массивом байт, не должно смущать или привносить что-то новое.

Значения, прочитанные из ячеек, следует считать оттенками серого.

Для лабораторной работы №5.

В ходе этой лабораторной потребуется соединять приложение и динамически подключаемую библиотеку, причём написанные на разных языках. Для интеграции уже готов интерфейс обновления битмапа. Чем делать уже выполненные наработки – приложением или библиотекой – каждый студент решает для себя сам; оба варианта допускаются и работоспособны.

Для этой и последующей лабораторных можно модифицировать интерфейс, опубликованный в содержимом, объявив (и реализовав) новые методы в интерфейсе-наследнике (но не изменив декларацию оригинального интерфейса). Однако, делать это совершенно необязательно.

В заголовочном файле, в котором описывался интерфейс и который следует передавать «обёртке», также надо описать функцию получения интерфейса, где сам интерфейс должен быть выходным параметром, а сама функция возвращала бы код успешности/неуспешности в формате HRESULT.

Это, позволит с одной стороны передавать экземпляр интерфейса (причём именно как интерфейс), а с другой – штатно обрабатывать возможные исключения.

Пример





Скачать файл (180.6 kb.)

Поиск по сайту:  

© gendocs.ru
При копировании укажите ссылку.
обратиться к администрации