Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Visual_Studio_2010

.pdf
Скачиваний:
109
Добавлен:
03.03.2016
Размер:
5.94 Mб
Скачать

Рис. 20.10. Страница свойств Librarian–General – Output File

Настройка свойств Librarian завершается нажатием клавиш «Применить» и «OK».

После осуществления всех настроек выполняются компиляция и сборка библиотеки. В процессе компиляции модули, входящие в состав библиотеки (файлы с расширением .c), сначала обрабатываются препроцессором языка C, затем компилируются независимо друг от друга. В результате получается набор файлов с расширением .obj, содержащих скомпилированный код библиотечных функций. Затем полученный набор объектных файлов (с расширением .obj) объединяется в библиотечный модуль (файл с расширением .lib).

Процесс сборки проекта статической библиотеки запускается из пункта меню Build Build containers. Результат выбора показан на рис.20.11.

371

Рис.20.11. Запуск компиляции и сборки библиотеки

Впроцессе сборки библиотеки компилятор и библиотекарь (Librarian) выводят в окно сообщений (Output) среды Visual Studio диагностическую информацию, содержащую результаты компиляции каждого из модулей, подключенных к проекту статической библиотеки, возможные предупреждения компилятора и конечную статистику (например, количество ошибок и предупреждений) сборки библиотеки (рис.20.12).

Врезультате произведенной компиляции получаем папку с именем созданной библиотеки (containers), где в папке Debug располагается двоичный объектный библиотечный модуль – файл с расширением .lib. Для данного слу-

чая это файл containers.lib.

372

Рис.20.12. Окно с сообщением об успешной компиляции библиотеки

Программные коды подключаемых файлов

// file stack.h

#ifndef STACK_H__ #define STACK_H__

/// by default a stack reserves space for 16 items #define STACK_INITIAL_CAPACITY 16

typedef struct stack {

///number of items in the stack int m_length;

///capacity of the stack

int m_capacity;

/// block of memory for the stack int *m_items;

} stack_t;

///create a new stack and returns it stack_t *stack_create (int capacity);

///destroys the stack and frees resources void stack_destroy (stack_t *stack);

///pushes an item into the stack

373

int stack_push (stack_t *stack, int item);

///pops the item from the stack int stack_pop (stack_t *stack);

///checks whether the stack is empty int stack_is_empty (stack_t *stack);

#endif

// file stack.c

#include <assert.h>

#include <malloc.h>

#include <stddef.h>

#include "stack.h"

static int stack_ensure_capacity (stack_t *stack, int capacity)

{

int capacityDesired; int *p;

if (stack->m_capacity >= capacity) return 1;

capacityDesired = stack->m_capacity * 2;

p = realloc (stack->m_items, capacityDesired * sizeof (int)); if (!p)

return 0;

stack->m_items = p; stack->m_capacity = capacityDesired; return 1;

}

stack_t* stack_create (int capacity) { stack_t *result;

if (capacity <= 0)

capacity = STACK_INITIAL_CAPACITY; result = malloc (sizeof (stack_t));

if (!result) return NULL;

result->m_items = malloc (capacity * sizeof (int)); if (!result->m_items) {

free (result); return NULL;

}

result->m_capacity = capacity;

result->m_length = 0; return result;

}

374

void stack_destroy (stack_t *stack)

{

assert (stack != NULL);

assert (stack->m_items != NULL);

free (stack->m_items); free (stack);

}

int stack_push (stack_t *stack, int item)

{

assert (stack != NULL);

assert (stack->m_capacity > 0); assert (stack->m_items != NULL);

if (!stack_ensure_capacity (stack, stack->m_length + 1)) return 0;

stack->m_items[stack->m_length++] = item; return 1;

}

int stack_pop (stack_t *stack)

{

assert (!stack_is_empty (stack));

return stack->m_items[--stack->m_length];

}

int stack_is_empty (stack_t *stack)

{

assert (stack != NULL);

return stack->m_length <= 0;

}

// file queue.h

#ifndef QUEUE_H__

#define QUEUE_H__

typedef struct queue_item

{

/// pointer to the next item in the queue

struct queue_item *m_next;

/// item data

int m_item;

} queue_item_t;

375

typedef struct queue

{

///number of items in the queue int m_length;

///first item in the queue struct queue_item *m_head;

///last items in the queue struct queue_item **m_tailnext;

}queue_t;

///creates a new queue and returns it queue_t *queue_create ();

///destroys the queue and frees resources void queue_destroy (queue_t *queue);

///pushes an item into the queue adding it to the queue's tail int queue_push (queue_t *queue, int item);

///pops the item from the queue, removing it from the queue's

head

int queue_pop (queue_t *queue);

/// checks whether the queue is empty int queue_is_empty (queue_t *queue);

#endif

// file queue.c #include <assert.h> #include <malloc.h>

#include <stddef.h>

#include "queue.h"

queue_t* queue_create ()

{

queue_t *queue;

queue = malloc (sizeof (queue_t)); if (!queue)

return NULL;

queue->m_head = NULL; queue->m_tailnext = &(queue->m_head); queue->m_length = 0;

return queue;

}

376

void queue_destroy (queue_t *queue)

{

queue_item_t *p; assert (queue != NULL);

for (p = queue->m_head; p != NULL; p = p->m_next) free (p);

free (queue);

}

int queue_push (queue_t *queue, int item)

{

queue_item_t *p; assert (queue != NULL);

assert (queue->m_tailnext != NULL);

// create new queue item and insert it into tail p = malloc (sizeof (queue_item_t));

if (!p) return 0;

p->m_next = NULL; p->m_item = item;

*queue->m_tailnext = p; queue->m_tailnext = &(p->m_next);

++queue->m_length; return 1; }

int queue_pop (queue_t *queue) { queue_item_t *p;

assert (!queue_is_empty (queue));

// detach head and return the item p = queue->m_head;

if (p) {

int item = p->m_item; queue->m_head = p->m_next;

//if the last one was removed than

//we should reset our tail

if (queue->m_tailnext == &(p->m_next)) queue->m_tailnext = &(queue->m_head);

free (p);

377

--queue->m_length;

assert (queue->m_length >= 0); return item;

}

assert (1 != 1);

// should not happen return 0;

}

int queue_is_empty (queue_t *queue)

{

assert (queue != NULL);

return queue->m_length <= 0;

}

Для работы с библиотекой следует подготовить проект с главной функцией main(), в которой с помощью директивы #include подключаются файлы, расположенные в созданной статической библиотеке. Для этих файлов необходимо указать путь, где они расположены. Обычно это делается с помощью нотации "..\..\stack.h", которая указывает, что файл stack.h находится на два уровня выше, чем функция main(), в которой он будет использоваться.

Настройка проекта с главной функцией main() выполняется при установке режима компиляции языка С системы MS Visual Studio 2010. Для этого в

меню системы MS Visual Studio последовательно выбирается File New Project. Далее из списка типа проекта Project types также последова-

тельно выбираются Visual C++ Win32 Win32 Console Application. В поле

Name прописывается имя проекта, например Lab20. Далее осуществляется настройка проекта в режиме компиляции языка С (см. тему 1).

При настройке параметров компилятора дополнительно необходимо указать компилятору пути к заголовочным файлам stack.h и queue.h, содержащим объявления интерфейса созданной библиотеки containers. Это можно сделать в пункте Additional Include Directories (дополнительные каталоги с заголовочными файлами) на странице свойств [C/C++]|[General]. Затем указывается путь к папке containers, в которой находятся библиотечные файлы stack.h/stack.с и queue.h/queue.с в виде ..\..\containers\ containers.

Форма с установкой пути к созданной статической библиотеке показана на рис. 20.13.

378

Рис.20.13. Установка пути к файлам созданной библиотеки

После настройки параметров компилятора необходимо выполнить настройку параметров компоновщика (Linker). На этапе компоновки происходит подключение статической библиотеки, из нее извлекается код уже скомпилированных функций, которые используются в основном проекте (с главной функцией main()). Кроме кода функций, компоновщик при необходимости извлекает из статической библиотеки совместно используемые глобальные переменные. После того как все ссылки на функции и переменные будут разрешены, компоновщик выполняет вычисление машинных адресов для функций и переменных в конечном исполняемом модуле.

На странице свойств [Linker]|[Input] необходимо указать путь к объектному файлу библиотеки. Форма с установкой свойств компоновщика показана на рис.20.14.

379

Рис.20.14. Настройка компоновщика Linker Input Additional Dependencies

После выполнения всех настроек можно компилировать программу и запускать ее на выполнение.

Проект с главной функцией main() и включенными заголовочными файлами из созданной библиотеки представлен на рис.20.15.

380

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]