Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Роджерсон Д. - Основы COM - 2000.pdf
Скачиваний:
412
Добавлен:
13.08.2013
Размер:
2.4 Mб
Скачать

166

на которые имеется ссылка. Поэтому не используйте в качестве типа параметра void*. Если Вам нужно передать абстрактный указатель на интерфейс, используйте IUnknown*. Самый гибкий метод — передача клиентом IID, и именно так работает QueryInterface:

HRESULT GetIFace([in] const IID& iid, [out, iid_is(iid)] IUnknown** ppi);

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

HRESULT GetMyInterface([out] IMyInterface** pIMy);

Но что произойдет, если будет возвращен IMy2 или IMyNewAndVastlyImproved?

Компилятор MIDL

Теперь, когда у нас есть файл IDL, его можно пропустить через компилятор MIDL, который сгенерирует несколько файлов. Если описания наших интерфейсов находятся в файле FOO.IDL, то скомпилировать этот файл можно следующей командой:

midl foo.idl

В результате будут сгенерированы файлы, перечисленные в табл. 10-1.

Таблица 10-1 Файлы, гененрируемые компилятором MIDL

Имя файла

Содержимое

 

 

FOO.H

Заголовочный файл (для С и С++), содержащий объявления всех интерфейсов, описанных

 

в файле IDL. Имя заголовочного файла можно изменить с помощью параметра командной

 

строки /header или /h.

FOO_I.C

Файл С, в котором определены все GUID, использованные в файле IDL. Имя файла можно

 

изменить с помощью параметра командной строки /iid.

FOO_P.C

Файл С, реализующий код заместителей и заглушек для всех описанных в файле IDL

 

интерфейсов. Имя файла можно изменять с помощью параметра командной строки /proxy.

DLLDATA.C

Файл С, реализующий DLL, которая содержит код заместителей и заглушек. Имя файла

 

можно изменить с помощью параметра командной строки /dlldata.

 

 

Если в файле IDL имеется ключевое слово library, то по приведенной выше команде будет сгенерирована библиотека типа. (Как Вы помните, более подробно библиотеки типа будут рассматриваться в восхитительной следующей главе этой книги.) На рис. 10-4 показаны файлы, генерируемые компилятором MIDL. Здесь также показано, как из этих файлов генерируется DLL заместителя, — процесс, который мы рассмотрим чуть ниже.

FOO.H

Эти файлы генерируются MIDL

 

 

FOO_P.C

 

 

 

 

FOO_I.C

 

 

FOO.IDL

MIDL.EXE

DLLDATA.C

Компилятор C

FOO.DLL

 

и

 

 

 

 

 

компоновщик

 

 

 

make-файл

 

 

 

 

FOO.DEF

 

REGSVR32.EXE

Эти файлы пишете Вы

 

 

 

 

Файл

 

 

 

 

определений

 

 

 

 

для DLL

 

 

Рис. 10-4 Получение и использование файлов, генерируемых компилятором MIDL

167

Сборка примера программы

Чтобы наш разговор был более предметным, давайте соберем пример программы для этой главы. Все необходимые файлы есть на прилагающемся к книге компакт-диске. С помощью make-файла примера можно построить две версии сервера компонента: SERVER.DLL и SERVER.EXE. Для того, чтобы построить обе версии сразу, используется команда

nmake –f makefile

MAKEFILE дважды вызывает файл MAKE-ONE для сборки двух разных версий сервера. Промежуточные файлы сервера внутри процесса будут помещены в подкаталог \INPROC. Промежуточные файлы сервера вне процесса будут помещены в подкаталог \OUTPROC.

В make-файлах этого примера для запуска MIDL используется следующая командная строка:

midl /h iface.h /iid guids.c /proxy proxy.c server.idl

Эта команда переименовывает файлы, генерируемые MIDL, чтобы мы могли использовать прежние имена. Вместо того, чтобы писать определения интерфейса и в IFACE.H, и в SERVER.IDL, мы создаем только SERVER.IDL, а компилятор MIDL по нему генерирует IFACE.H автоматически. Точно так же нам более нужны GUID в файле GUID.CPP. Теперь мы просто подключаем GUIDS.C.

Заголовочный файл, генерируемый MIDL, можно использовать в программах как на С, так и на С++. Единственный недостаток этих заголовочных файлов в том, что они практически нечитабельны. Вы поймете, что имеется в виду, если посмотрите на содержимое сгенерированного MIDL файла IFACE.H. Как видите, его нелегко расшифровать. Тем не менее, это гораздо лучше, чем вручную поддерживать одинаковые описания интерфейса в разных местах.

Сборка DLL заместителя

Чтобы получить DLL заместителя/заглушки, нужно откомпилировать и скомпоновать файлы C, сгенерированные MIDL. Компилятор MIDL генерирует для нас код на С, который реализует для наших интерфейсов заместители и заглушки. Однако мы по-прежнему должны сами скомпилировать эти файлы в DLL. Первый шаг — написать для DLL заглушку файла DEF. Это очень просто. Файл DEF, который я использую, приведен ниже.

LIBRARY

Proxy.dll

 

DESCRIPTION

‘Proxy/Stub DLL’

 

EXPORTS

 

 

 

DllGetClassObject

@1 PRIVATE

 

DllCanUnloadNow

@2 PRIVATE

 

GetProxyDllInfo

@3 PRIVATE

 

DllRegisterServer

@4 PRIVATE

 

DllUnregisterServer

@5 PRIVATE

Теперь осталось все это откомпилировать и скомпоновать. Как это сделать, показывает следующий фрагмент файла MAKE-ONE:

iface.h server.tlb proxy.c guids.c dlldata.c : server.idl midl /h iface.h /iid guids.c /proxy proxy.c server.idl

!IF “$(OUTPROC)” != “” dlldata.obj : dlldata.c

cl /c /DWIN32 /DREGISTER_PROXY_DLL dlldata.c

proxy.obj : proxy.c

 

cl /c /DWIN32 /DREGISTER_PROXY_DLL proxy.c

PROXYSTUBOBJS = dlldata.obj

\

proxy.obj

\

guids.obj

 

PROXYSTUBLIBS = kernel.lib

\

rpcndr.lib

\

rpcns4.lib

\

rpcrt4.lib

\

uuid.lib

 

proxy.dll : $(PROXYSTUBOBJS) proxy.def

 

link /dll /out:proxy.dll /def:proxy.def

\

$(PROXYSTUBOBJS) $(PROXYSTUBLIBS)

 

regsvr32 /s proxy.dll

 

Соседние файлы в предмете Программирование на C++