COM C#, 如何使用 C++ 调用 COM
Posted
技术标签:
【中文标题】COM C#, 如何使用 C++ 调用 COM【英文标题】:COM C#, How to use C++ to call COM 【发布时间】:2013-04-29 03:16:06 【问题描述】:我使用了一个 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;
【问题讨论】:
您有#import
声明吗?这是基于 COM 类型库 (.tlb) 生成类的 Visual Studio 扩展。 msdn.microsoft.com/en-us/library/8etzzkb6%28v=vs.71%29.aspx
【参考方案1】:
如果你的代码有效,那是因为在 C++ 项目的某个地方,定义了以下语句(例如,如果你使用 #import directive,它是自动的):
_COM_SMARTPTR_TYPEDEF(ICalc, __uuidof(ICalc));
_COM_SMARTPTR_TYPEDEF 是一个在ICalc
上定义“智能指针”的宏。这是一个 Microsoft Visual C++ 神奇的扩展,用于更轻松的 COM 支持。官方文档在这里:_com_ptr_t Class
智能指针通常由 typedef 定义引用 _COM_SMARTPTR_TYPEDEF 宏提供。这个宏需要一个 接口名称和 IID 并声明 _com_ptr_t 的特化 接口名称加上后缀Ptr。
【讨论】:
谢谢,这正是我需要的。顺便说一句,我是 COM 和智能指针的更新者。你建议我需要学习什么,因为我面临一个需要使用基于 COM 的 API 的项目。我手头有>。 哇,这在我的脑海里已经过时了 :-) 我有 Essential COM 是的,还有 Wrox 的“专业 DCOM 编程”、“专业 ATL COM 编程”以及“ATL 内部:”。请注意,如果您了解 ATL,您将了解 COM 的真正工作原理。 ATL 不是必需的,但它是学习 COM 的一种方式。 至少阅读“基本 COM”的前 4 章 - 它涵盖了编写 COM 客户端所需了解的 >90%。不过,.NET 和 C++ 之间的 COM 互操作部分可能很复杂。 谢谢你们。你很有帮助【参考方案2】:我不确定您使用什么工具将 .NET 类导出到 C++,但我怀疑 COMLib::ICalPtr 只是智能指针类的 typedef,它管理其中的底层原始指针。
您是否尝试过在调试器中单步执行以查看 CreateInstance 的实现是做什么的?我怀疑您会看到最终调用 CoCreateInstance 和可能 QueryInterface 的自动生成的代码。也许一些代码可以将 Factorial 等方法转换为 IDispatch::Invoke() 调用。
【讨论】:
【参考方案3】:ICalcPtr 保存由 COM 创建的类的实例。
出于同样的原因,我们不能从 c++ dll 导出类,COM 对象必须返回到接口。
http://www.codeproject.com/Articles/28969/HowTo-Export-C-classes-from-a-DLL
这篇文章帮助我理解了这个概念。
现在,selbie 是正确的,接口名称末尾的 PTR 是指向接口的智能指针。出于您的目的,它本质上是透明的,可以将其视为只是 ICalc 对象。但是,它会自动为您进行清理。 ICalcPtr 在幕后为您生成。
【讨论】:
以上是关于COM C#, 如何使用 C++ 调用 COM的主要内容,如果未能解决你的问题,请参考以下文章