3

我使用了一个 C# COM 的在线示例,并通过 C++ 调用它。以下是C# COM 代码,只有一个接口“ICalc”和一个类“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;
    }
}
}

以下代码在 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;
4

3 回答 3

2

如果您的代码有效,那是因为在 C++ 项目的某个地方,定义了以下语句(例如,如果您使用#import 指令,它是自动的):

_COM_SMARTPTR_TYPEDEF(ICalc, __uuidof(ICalc));

_COM_SMARTPTR_TYPEDEF 是一个宏,它在ICalc. 这是一个 Microsoft Visual C++ 神奇的扩展,用于更轻松的 COM 支持。官方文档在这里:_com_ptr_t Class

智能指针通常由 _COM_SMARTPTR_TYPEDEF 宏提供的 typedef 定义引用。该宏采用接口名称和 IID 并声明 _com_ptr_t 的特化,其接口名称加上Ptr后缀。

于 2013-05-05T06:32:04.273 回答
0

ICalcPtr 保存由 COM 创建的类的实例。

出于同样的原因,我们不能从 c++ dll 导出类,COM 对象必须返回到接口。

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

这篇文章帮助我理解了这个概念。

现在,selbie 是正确的,接口名称末尾的 PTR 是指向接口的智能指针。出于您的目的,它本质上是透明的,可以将其视为只是 ICalc 对象。但是,它会自动为您进行清理。ICalcPtr 在幕后为您生成。

于 2013-05-05T03:37:33.417 回答
0

我不确定您使用什么工具将 .NET 类导出到 C++,但我怀疑 COMLib::ICalPtr 只是智能指针类的 typedef,它管理其中的底层原始指针。

您是否尝试过在调试器中单步执行以查看 CreateInstance 的实现是做什么的?我怀疑您会看到最终调用 CoCreateInstance 和可能 QueryInterface 的自动生成的代码。也许一些代码可以将 Factorial 等方法转换为 IDispatch::Invoke() 调用。

于 2013-05-05T01:54:46.153 回答