вторник, 21 июня 2011 г.

Первый шаг в мир Windows API

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

Возникает вопрос: что доступно из WinAPI пользователям D? Базовая поддержка необходимых функций есть как в фобосе, так и в танго. Для наших целей (повторю, что цель блога — создание игр на Direct3D9), вероятно, их будет достаточно. В случае, если встроенного функционала будет не хватать, воспользуемся библиотекой «Windows API Bindings». Проверим взаимодействие с операционной системой на примере простого приложения, содержащего точку входа, отвечающую правилам WinAPI.

Самый первый и главный вопрос: с чего начать? Вообще, когда передо мной новый язык или новая технология, первое, что я обычно делаю — ищу источник достоверной информации. Все что касается языка, доступно на официальном сайте, что касается WinAPI — все есть в MSDN. Правда весь нужный текст на английском языке.
Именно отсутствие подобной информации на русском языке является причиной появления этого блога. Если об использовании WinAPI в С++ еще можно найти информацию в сети, то про Ди такого точно нигде нет. Но в любом случае, я не ставлю перед собой цель научить вас — это слишком большая ответственность.
Все что я могу гарантировать, это то, что прилагаемые примеры скомпилируются и запустятся. Не больше, не меньше. Я конечно стараюсь проявлять максимальную техническую грамотность, на случай, если кто-нибудь будет читать этот блог, но ведь я сам еще только осваиваю рассматриваемые технологии, поэтому мне доподлинно наперед не известно, насколько правильными являются мои действия. Я лишь демонстрирую процесс обучения, рассказывая о проделанных действиях.
Зачем? Ну, во-первых, очень интересно, как воспримет мои рассказы общественность. Во-вторых, про D, особенно в русском сегменте сети, очень мало информации. В-третьих, данные тексты можно воспринимать как обучающие, посему они несут еще большую полезность.
Моей задачей, в конечном итоге, является предоставление «информации к размышлению, сведению». Если вам интересно — пожалуйста, пользуйтесь. Я ни в коем случае не рассчитываю на абсолютную точность и достоверность информации, поскольку получена она на личном опыте, а я — умею ошибаться. Поэтому советую всегда и во всем иметь свою точку зрения, не принимать все близко к сердцу, каким бы авторитетным не казался источник.
Это было последнее отступление, больше мы к правилам пользования информацией возвращаться не будем.

Итак, в конечном итоге, планируется написание игры. Что от операционной системы нужно игре? Работа с файлами, сетью, графическим интерфейсом, устройствами ввода. Начнем с основ: любое приложение имеет так называемую «точку входа» — функцию, которая начинает работу программы. Любое графическое приложение в операционной системе Windows должно начинаться с WinMain, шаблон которой на C++ выглядит как:

int CALLBACK WinMain(
  __in  HINSTANCE hInstance,
  __in  HINSTANCE hPrevInstance,
  __in  LPSTR lpCmdLine,
  __in  int nCmdShow);

Вместо классического, где передается лишь командная строка приложения, этот метод предлагает четыре параметра: указатель на текущий экземпляр приложения (hInstance), указатель на предыдущий экземпляр приложения (hPrevInstance), командную строку для приложения (lpCmdLine, которая не включает путь к приложению) и специальное значение, описывающее характер отображения приложения (nCmdShow).
Между делом, на досуге, советую прочесть заметку о конверсии D-C строк, поскольку речь заходит о строках в WinAPI, который написан на голом C.
Как теперь реализовать шаблон этого метода в D? Поскольку я использую tango, то код будет выглядеть так:
import tango.sys.win32.Types;

extern (Windows)
int WinMain(
  HINSTANCE hInstance,
  HINSTANCE hPrevInstance,
  LPSTR lpCmdLine,
  int nCmdShow)
{
   return 0;
}
Понятное дело, что нужно сначала импортировать модуль, содержащий типы WinAPI. Затем, можно объявить функцию так же, как она объявляется в C++. Единственное, что осталось — привести функцию в соответствие требованиям Windows API. За это отвечает extern (Windows). Применяя такой атрибут, компилятор будет знать, что для этой функции необходимо использовать __stdcall в качестве модели вызова функции. При этом, линковщик позаботится о правильном манглировании имен.

В результате мы получим приложение, полностью совместимое с WinAPI на программном уровне.

Архив с проектом.

Комментариев нет:

Отправить комментарий