2013-05-05 2 views
3

Я использовал онлайн-пример C# COM и назову его через C++. Ниже приведен код C# COM, только один интерфейс «ICalc» и один класс «Calc».COM C#, Как использовать C++ для вызова COM

namespace COMLib 
{ 
[Guid("F40D7BC9-CF53-4613-AA5E-F269AD73808F")] 
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] 
public interface ICalc 
{ 
    [DispId(1)] 
    long Factorial(int n); 
} 

[Guid("8EE38F2E-75BE-4B45-87B6-3F6D15FDBBC5")] 
[ClassInterface(ClassInterfaceType.None)] 
[ComSourceInterfaces(typeof(ICalc))] 
[ProgId("MyCalc")] 
public class Calc : ICalc 
{ 
    long ICalc.Factorial(int n) 
    { 
     long fact = 1; 
     for (int i = 1; i <= n; i++) 
      fact *= i; 
     return fact; 
    } 
} 
} 

Следующий код находится на C++ для вызова этой функции. Он работает. Однако меня путают с кодом во второй строке. откуда происходит «ICalcPtr»? Или это какой-то механизм?

CoInitialize(NULL); 
    COMLib::ICalcPtr pCalc; 
    HRESULT hRes = pCalc.CreateInstance(__uuidof(COMLib::Calc)); 
    if(FAILED(hRes)) 
     printf("ICalcPtr::CreateInstance failed w/err 0x%08lx\n", hRes); 
    else 
    { 
     printf("%d\n", pCalc->Factorial(3)); 
    } 
    system("pause"); 
    CoUninitialize(); 
    return 0; 
+0

У вас есть заявление '# import'? Это расширение Visual Studio, которое генерирует классы на основе библиотеки типа COM (.tlb). http://msdn.microsoft.com/en-us/library/8etzzkb6%28v=vs.71%29.aspx – shf301

ответ

2

Если вы код работает, его потому, что где-то в проекте C++, есть следующий оператор определяется (это автоматически, если вы использовали #import directive, например):

_COM_SMARTPTR_TYPEDEF(ICalc, __uuidof(ICalc)); 

_COM_SMARTPTR_TYPEDEF макрос, который определяет " умный указатель "на ICalc. Это магическое расширение Microsoft Visual C++ для упрощения поддержки COM. Официальная документация находится здесь: _com_ptr_t Class

Умный указатель обычно ссылаются на определении ЬурейеГо предоставленного _COM_SMARTPTR_TYPEDEF макрокоманда. Этот макрос принимает имя интерфейса и IID и объявляет специализацию _com_ptr_t с именем интерфейса плюс суффикс Ptr.

+0

Спасибо, это то, что мне нужно. BTW, я новичок в COM и умном указателе. Что вы предлагаете мне учиться, потому что я сталкиваюсь с проектом, который должен использовать API на основе COM. Я получил << существенный COM >> под рукой. –

+0

Ничего себе, это на мой взгляд :-) У меня был Essential COM да, и Wrox's «Профессиональное программирование DCOM», «Профессиональное программирование ATL COM» и «ATL Internals:». Обратите внимание, что если вы понимаете ATL, вы узнаете, как работает COM. ATL не требуется, но это один из способов узнать COM. –

+0

прочитайте хотя бы первые 4 главы «Essential COM» - он охватывает> 90% того, что вам нужно знать для написания COM-клиентов. Однако часть взаимодействия COM между .NET и C++ может быть волосатой. –

0

Я не уверен, какие инструменты вы использовали, чтобы экспортировать класс .NET в C++, но я подозреваю, что COMLib :: ICalPtr просто ЬурейеЕ в смарт-класс указателя, который управляет лежащий в основе сырой указатель внутри него.

Вы пробовали переходить в отладчик, чтобы узнать, что делает реализация CreateInstance? Я подозреваю, что вы видите автоматически сгенерированный код, который в конечном итоге вызывает CoCreateInstance и, возможно, QueryInterface. Возможно, некоторый код для перевода таких методов, как Factorial, в вызовы IDispatch :: Invoke().

0

ICalcPtr содержит экземпляр вашего класса, созданный COM.

По той же причине мы не можем экспортировать классы из dll C++, COM-объекты должны быть возвращены в интерфейс.

http://www.codeproject.com/Articles/28969/HowTo-Export-C-classes-from-a-DLL

Эта статья помогла мне понять эту концепцию.

Теперь, selbie правильно, PTR в конце вашего имени интерфейса является умным указателем на ваш интерфейс. Для ваших целей он по существу прозрачен и может обрабатываться так, как если бы он был справедливым и ICalc-объектом. Тем не менее, он позаботится об очистке для вас автоматически. ICalcPtr генерируется для вас за кулисами.