3

I used a online example of C# COM and call it through C++. The following is the C# COM code, only one interface "ICalc" and one class "Calc".

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;
    }
}
}

The following code is in C++ to call this this function. It is worked. However, I am confused with the code in second line. where is the "ICalcPtr" come from? Or is this some mechanism?

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;
1

3 Answers 3

2

If you code works, its because somewhere in the C++ project, there is the following statement defined (it's automatic if you used a #import directive for example):

_COM_SMARTPTR_TYPEDEF(ICalc, __uuidof(ICalc));

_COM_SMARTPTR_TYPEDEF is a macro that defines a "smart pointer" on ICalc. It's a Microsoft Visual C++ magical extension for easier COM support. The official documentation is here: _com_ptr_t Class

A smart pointer is usually referenced by the typedef definition provided by the _COM_SMARTPTR_TYPEDEF macro. This macro takes an interface name and the IID and declares a specialization of _com_ptr_t with the name of the interface plus a suffix of Ptr.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, that's what I need. BTW, I am a newer of COM and smart pointer. What do you suggest I need to learn because I am facing a Project need to use API based on COM. I got <<essential COM>> at hand.
Wow, that's old in my mind :-) I had Essential COM yes, and Wrox's 'Professional DCOM programming', 'Professional ATL COM programming', plus 'ATL Internals:'. Note if you understand ATL, you will learn how COM works really. ATL is not necessary, but it's one way to learn COM.
read at least first 4 chapters of 'Essential COM' - it covers >90% of what you need to know for writing COM clients. The COM interop part between .NET and C++ can be hairy, though.
0

I'm not sure what tools you used to export the .NET class to C++, but I suspect COMLib::ICalPtr is simply a typedef to a smart pointer class that manages an underlying raw pointer inside it.

Have you tried stepping through in the debugger to see what the implementation of CreateInstance does? I suspect you see auto-generated code that eventually calls CoCreateInstance and possibly QueryInterface. Maybe some code to translate methods like Factorial into IDispatch::Invoke() calls.

Comments

0

ICalcPtr holds the instance of your class that is created by COM.

For the same reason we cannot export classes from a c++ dll, COM objects must be returned to an interface.

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

This article helped me understand the concept.

Now, selbie is correct, the PTR at the end of your interface name is a smartpointer to your interface. For your purposes it's is essentially transparent and can be treated as if it was just and ICalc object. It will however take care of cleanup for you automatically. ICalcPtr is generated for you behind the scenes.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.