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

2019-07-07 01:21发布

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;

标签: c# c++ com
3条回答
唯我独甜
2楼-- · 2019-07-07 01:25

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.

查看更多
不美不萌又怎样
3楼-- · 2019-07-07 01:27

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.

查看更多
唯我独甜
4楼-- · 2019-07-07 01:43

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.

查看更多
登录 后发表回答