简体   繁体   中英

COM C#, How to use C++ to call COM

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;

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 . 声明_com_ptr_t的特化。

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM