Uuid(EE0BAF52-B2DB-4CC7-BD5E-9DB352699F3F)

pointer_default(unique)

]

interface IMathem2 : IUnknown{

};

// конец добавлений

[

Uuid(946AB57D-27B2-480A-B3A9-D90E2398D356),

Version(1.0),

]

Library DLLMathServerLib

{

importlib("stdole2.tlb");

[

Uuid(DA4D3129-504E-4E42-AE02-BCBB9771118C)

]

Coclass Mathem

{

[default] interface IMathem;

Interface IMathem2; // добавлено

};

};

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

Созданный нами новый интерфейс надо добавить собственными ручонками в объявление класса CMathem в файле Mathem.h, в результате чего этот файл (ниже показан только его фрагмент) должен стать таким (изменения выделены цветом и комментарием «добавлено»):

// CMathem

class ATL_NO_VTABLE CMathem :

public CComObjectRootEx<CComSingleThreadModel>,

public CComCoClass<CMathem, &CLSID_Mathem>,

Public IMathem,

Public IMathem2 // добавлено

{

public:

CMathem()

{

}

DECLARE_REGISTRY_RESOURCEID(IDR_MATHEM)

DECLARE_NOT_AGGREGATABLE(CMathem)

BEGIN_COM_MAP(CMathem)

COM_INTERFACE_ENTRY(IMathem)

COM_INTERFACE_ENTRY(IMathem2) // добавлено

END_COM_MAP()

После этих модификаций библиотека должна компилироваться и собираться без ошибок – поверьте, но проверьте!

Шаг 5.Добавление новых методов и свойств.

Для добавления новых методов необходимо действовать так же, как и при добавлении методов к интерфейсу по умолчанию (см. инструкции к шагу 3). Возможно, что реализацию методов нового интерфейса придется добавлять вручную в файл реализации Mathem.cpp. Также, очевидно, надо будет добавить объявление (прототип) новых методов в заголовочный файл Mathem.h по аналогии с методами первого интерфейса.

Самостоятельно выберите какой-нибудь метод, обрабатывающий массив, и добавьте его в интерфейс IMathem2. Параметр-массив надо объявлять как указатель, например, LONG *, CHAR * или DOUBLE *, так как методы СОМ объектов не поддерживают параметры структурных типов. Добавьте также еще один метод к любому интерфейсу и свойство (property). Тип свойства опять-таки выберите по своему усмотрению, напишите реализацию методов установки и чтения значения свойства. Для хранения значения свойства добавьте в класс CMathem член-переменную для достижения этой возвышенной цели.

В качестве примера полезного метода рассмотрим такую задачу. Во многих инженерных расчетах используются исходные данные, заданные таблично. Например, на рис. 3 приведена иллюстрация метода использования таблично-заданной функции Y(X) для получения значения функции YK для заданного значения аргумента XK.

 
  Uuid(EE0BAF52-B2DB-4CC7-BD5E-9DB352699F3F) - student2.ru

Рис. 3. Интерполяция таблично-заданных значений функции Y(X)

Для знающего математику даже в объема школьного курса понятно, что в качестве исходных данных надо иметь:

· массив значений функции Y;

· массив значений аргумента функции X;

· значение аргумента Xk, для которого требуется определить значение функции Yk.

Также совершенно очевидно, что задача определения Yk по Xk сводится к линейной интерполяции значений функции на известном отрезке Xi<=Xk<=Xi+1, что также не выходит за рамки начальных знаний геометрии на плоскости.

Этот пример метода не только полезный, но и необходимый для реализации в вашем сервере.

При добавлении в интерфейс свойства с помощью мастера (последовательность действий такая же, как и для метода) в окне Add Property Wizard достаточно указать только тип свойства (выбрать в списке Property type) и ввести его имя (поле Prpoperty name). Больше ничего вводить или изменять в данном случае не нужно. Например, если задать имя свойства Foo и выбрать для него тип BSTR, то в файле DLLMathServer.idl появятся строки, выделенные полужирным шрифтом:

interface IMathem : IUnknown{

[helpstring("method Cube")] HRESULT Cube([in] DOUBLE Arg,

[out] DOUBLE* Res);

[propget, helpstring("property Foo")] HRESULT Foo([out, retval] BSTR* pVal);

[propput, helpstring("property Foo")] HRESULT Foo([in] BSTR newVal);

};

Для доступа к свойству Foo мастер сгенерирует два метода:

/////////////// в файле Mathem.h

STDMETHOD(get_Foo)(BSTR* pVal);

STDMETHOD(put_Foo)(BSTR newVal);

////////////// в файле Mathem.cpp

STDMETHODIMP CMathem::get_Foo(BSTR* pVal)

{

// TODO: Add your implementation code here

return S_OK;

}

STDMETHODIMP CMathem::put_Foo(BSTR newVal)

{

// TODO: Add your implementation code here

return S_OK;

}

Если мы собираемся хранить значение этого свойства в классе CMathem (а не получать его от господа бога или дьявола), то надо, очевидно, добавить в этот класс соответствующий компонент. Например, опишем в классе CMathem (файл Mathem.h) такой член-данное и инициализируем его в конструкторе:

BSTR m_bstrFoo; // добавлено

public:

CMathem()

{

m_bstrFoo=0; // добавлено

}

Реализация методов чтения и записи значения свойства Foo может быть выполнена следующим образом (файл Mathem.cpp):

STDMETHODIMP CMathem::get_Foo(BSTR* pVal)

{

*pVal=SysAllocString(m_bstrFoo);

return S_OK;

}

STDMETHODIMP CMathem::put_Foo(BSTR newVal)

{

SysFreeString(m_bstrFoo);

m_bstrFoo=SysAllocString(newVal);

return S_OK;

}

Обращаю ваше внимание на то, что работа со строками BSTR существенно отличается от работы с другими типами строк: для выделения и освобождения памяти надо использовать специальные функции выделения и освобождения памяти: SysAllocString() и SysFreeString() вместо привычных операций new и delete.

В клиентском приложении использование свойства (но только с применением интеллектуальных указателей на интерфейс) будет выглядеть так же, как и в Object Pascal, а именно:

pMathem->Foo=_T("Property testing");

wcout<<"Property Foo=="<<pMathem->Foo<<endl;

Как пишут писатели, внимательный читаттель обратит внимание на то, что метод get_Foo() извращает результат не посредством своего имени, а посредством параметра, в то время как вызов этого метода выглядит так, как будто это функция, возвращающая строку?! Чудеса, глюки или и то и другое вместе? Разбирайтесь.

Регистрация сервера в реестре Windows.

В версии MVS-2010 (как и в версиях 2005 и 2008) сервер автоматически регистрируется после его успешной сборки. Альтернативный способ регистрации сервера, как уже указывалось выше, состоит в подаче команды

Regsvr32 путь\имя_сервера

из командной строки. Например:

Regsvr32 C:\Temp\Lab4\DLLMathServer\Debug\DLLMathServer.dll

Разрегистрировать сервер можно с помощью команды

Regsvr32 /u путь\имя_сервера

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

Для тестирования сервера надо разработать клиентское приложение, которое может быть консольным приложением, приложением Win32, оконным приложением и др. Вот за него, с большим энтузиазмом, и возьмемся двумя руками.


Наши рекомендации