COM в быту: первые шаги.
Я буду описывать процесс создания COM компонента на примере Visual Studio 2008 с использованием ATL, язык С++.
Для начала создаем проект Visual C++/ATL как показано на картинке:
Жмем «ОК», и выбираем опцию «Allow merging of proxy/stub code»:
Жмем «Finish». В итоге студия создаст нам проект и в Solution Explorer мы увидим такие файлы:
Это, так сказать, «оболочка». Т.е. если сейчас скомпилировать и собрать проект, то на выходе получим DLL файл, в котором пока нет никаких компонентов.
Для того, чтобы в нашем проекте появился некий компонент, изучим файл «FirstCOM.idl» – файл, в котором хранятся описания интерфейсов.
Пока в нем есть только это (за вычетом коментариев):
import "oaidl.idl";
import "ocidl.idl";
[
uuid(0652E0B7-4360-4542-8D22-8F52940AEFCE),
version(1.0),
helpstring("FirstCOM 1.0 Type Library")
]
library FirstCOMLib
{
importlib("stdole2.tlb");
};
Т.е. пока у нас описана только библиотека типов, которая называется FirstCOM, но нет самих типов. Причем, аттрибутом «version» задана версия нашей библиотеки типов, а «helpstring» – это описание библиотеки.
Добавляем наш компонент. Из контекстного меня нашего проекта выбираем «Add -> Class»:
Выбираем «ATL Simple Object»:
Далее вводим информацию о классе как показано на картинке:
И жмем «Finish». Студия создаст необходимые файлы и добавит в ресурсы константы. Помимо этого, файл «FirstCOM.idl» станет выглядеть так:
import "oaidl.idl";
import "ocidl.idl";
[
object,
uuid(5F9CB782-BDE1-48E3-91CC-E8EC0280EFA0),
dual,
nonextensible,
helpstring("IFirstCOMClass Interface"),
pointer_default(unique)
]
interface IFirstCOMClass : IDispatch
{
};
[
uuid(FD0B5C1A-6E02-4EFA-958B-046A0AD17381),
version(1.0),
helpstring("FirstCOM 1.0 Type Library")
]
library FirstCOMLib
{
importlib("stdole2.tlb");
[
uuid(61A52F01-320D-41E4-B5F2-A59C6E220292),
helpstring("FirstCOMClass Class")
]
coclass FirstCOMClass
{
[default] interface IFirstCOMClass;
};
};
Т.е. в секцию описания библиотеки (library FirstCOMLib{…}) добавилось описание класса (компонента) с неким интерфейсом IFirstCOMClass. А так же в начало файла добавилось само описание этого интерфейса.
Итого, мы добавили компонент (класс) FirstCOMClass, и указали его интерфейс – IFirstCOMClass. Интерфейс нужен для того, чтобы можно было получить доступ к нашему компоненту.
Теперь необходимо описать те методы и функции, которые будут в нашем компоненте. Пусть, например, мы хотим добавить 2 метода: метод, складывающий 2 числа и возвращающий результат; и метод, вычисляющий длину строки. И еще добавим 1 свойство «Author», с доступом на чтение и запись. Для этого в секцию
interface IFirstCOMClass : IDispatch
{
};
добавляем описания наших методов и свойств. Получим:
interface IFirstCOMClass : IDispatch
{
[id(1)] HRESULT CalcSumm([in] LONG lParam1, [in] LONG lParam2,
[out, retval] LONG* retVal);
[id(2)] HRESULT GetStringLen([in] BSTR strParam,
[out, retval] LONG* retVal);
[propget, id(3)]
HRESULT Author([out, retval] BSTR* retVal);
[propput, id(3)]
HRESULT Author(BSTR strValue);
};
Здесь:
[id(N)] – обозначает номер метода/свойства, должен быть уникальным;
[in] – обозначает входной параметр;
[out, retval] – выходной параметр.
Важно. Свойства на чтение и запись имеют как одно имя, так и номер (id).
Теперь нужно описать эти же методы в классе CFirstCOMClass, который будет реализовывать заявленный интерфейс. Ищем файл «CFirstCOMClass.h», в нем видим такое объявление класса:
class ATL_NO_VTABLE CFirstCOMClass :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CFirstCOMClass, &CLSID_FirstCOMClass>,
public IDispatchImpl<IFirstCOMClass, &IID_IFirstCOMClass,
&LIBID_FirstCOMLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
Это описание и позволяет компилятору связать наш COM класс и его интерфейс с реальным С++ классом.
В секцию public, добавляем такой код:
public:
STDMETHOD(CalcSumm)(LONG lParam1, LONG lParam2, VARIANT_BOOL* retVal);
STDMETHOD(GetStringLen)(BSTR strParam, VARIANT_BOOL* retVal);
STDMETHOD(get_Author)(BSTR* sVal);
STDMETHOD(put_Author)(BSTR sVal);
Кстати, рекомендую так же объявить деструктор и реализацию конструктора и деструктора перенести в файл «CFirstCOMClass.cpp».
Важно. Обратите внимание, что к методам чтения и записи свойства «Author» нужно добавить префиксы «get_» и «put_».
Далее создаем секцию «private» и добавим строку, для хранения значения нашего свойства «Author»:
private:
CComBSTR m_author;
А в файле «CFirstCOMClass.cpp» пишем:
// FirstCOMClass.cpp : Implementation of CFirstCOMClass#include "stdafx.h"
#include "FirstCOMClass.h" // CFirstCOMClass
CFirstCOMClass::CFirstCOMClass()
{
// initial value of the property Author
m_author = OLESTR("Vasya");
}
CFirstCOMClass::~CFirstCOMClass()
{
}
STDMETHODIMP CFirstCOMClass::CalcSumm(LONG lParam1, LONG lParam2, LONG* retVal)
{
// if pointer is invalid - return error
if (!retVal)
return S_FALSE;
*retVal = lParam1 + lParam2;
// no errors - return OK
return S_OK;
}
STDMETHODIMP CFirstCOMClass::GetStringLen(BSTR strParam, LONG* retVal)
{
// if pointer is invalid - return error
if (!retVal)
return S_FALSE;
CComBSTR str(strParam);
*retVal = (LONG)str.Length();// no errors - return OK
return S_OK;
}
STDMETHODIMP CFirstCOMClass::get_Author(BSTR* retVal)
{
// if pointer is invalid - return error
if (!retVal)
return S_FALSE;
// don't forget to allocate memory for the result string
*retVal = SysAllocString((BSTR)m_author);// no errors - return OK
return S_OK;
}STDMETHODIMP CFirstCOMClass::put_Author(BSTR newVal)
{
CComBSTR newAuthor(newVal);
m_author = newAuthor;// no errors - return OK
return S_OK;
}
В принципе, наша COM библиотека готова. Мы описали саму библиотеку, класс и интерфейс. А так же добавили реализацию интерфейса. Осталось только узнать как называется наша COM библиотека и класс. Их имена можно найти в файле «FirstCOMClass.rgs». Открывем его и ищем «VersionIndependentProgID»:
VersionIndependentProgID = s 'FirstCOM.FirstCOMClass'
Т.е. библиотека называется «FirstCOM», а класс – «FirstCOM.FirstCOMClass».
Если мы добавим еще несколько классов, то для каждого из них будет создан «.rgs» файл, и там так же будет написано :
VersionIndependentProgID = s 'FirstCOM._имя_класса_'
Собираем проект и в папке «Debug» или «Release» найдем файл «FirstCOM.dll» – это и есть наша COM библиотека. Для того, чтобы пользоваться ей на другом компьютере нужно зарегистрировать ее в системе. Это делается либо через инсталлятор, либо через команду:
regsvr32 FirstCOM.dll
Осталось проверить, работает ли все, что мы написали. Для этого напишем тестовый скрипт на VBS (Visual Basic Script). Создаем текстовый файл «test.vbs» и в нем пишем:
' create COM object, use library name and class name
Set comObj = CreateObject("FirstCOM.FirstCOMClass")
' test CalcSumm method
res = comObj.CalcSumm(1, 2)
WScript.Echo "1 + 2 = " & res
' test GetStringLen method
res = comObj.GetStringLen("QwertY123")
WScript.Echo "Len = " & res
' read property Author
auth = comObj.Author
WScript.Echo "Author = " & auth
' read property Author
comObj.Author = "Petya"
auth = comObj.Author
WScript.Echo "Author = " & auth
' cleanup
Set comObj = Nothing
Сохраняем файл и запускаем его так:
wscript.exe test.vbs
или
cscript.exe test.vbs
Если все сделано правильно, то мы увидим несколько текстовых сообщений, сообщающих нам результаты наших проверок.
Или вот пример использования на PHP:
<?php
// create COM object, use library name and class name
$comObj = new COM("FirstCOM.FirstCOMClass") or die("Can't create COM.");
// test CalcSumm method
$res = $comObj.CalcSumm(1, 2);
echo("1 + 2 = " . $res);
// test GetStringLen method
$res = $comObj.GetStringLen("QwertY123");
echo("Len = " . $res);
// read property Author
$auth = $comObj.Author;
$echo("Author = " . $auth);
// read property Author
$comObj.Author = "Petya";
$auth = $comObj.Author;
echo("Author = " . $auth);
// cleanup
$comObj = null;
?>
Как использовать COM из С/С++ и .NET приложений, вы можете посмотреть, например, здесь.
Скачать исходный код тестового COM проекта можно здесь.
Максим Филимонов.





Техподдержка
Обновления
Прайс-лист
Скачать
Онлайн-игры
Галерея
Форумы
Блог