我想在这个项目中使用C(而不是C ++),因为C ++有点可怕。在Visual Studio中更改项目的C / C ++设置以将其编译为C代码后,我注意到任何对
__uuidof
的调用都无法工作,因为它们是C ++特定的。我的问题有两个方面:
- 是否可能编写纯C的Win32程序来利用COM,以及
- 如果可以,是否应避免使用纯C?
__uuidof
的调用都无法工作,因为它们是C ++特定的。是的,使用纯C编写利用COM的程序是可能的,事实上在10-15年前这是常见做法。
使用C并不是一个好主意(正如你已经发现的那样)。例如,ATL在做COM时提供了很多帮助,并可以帮助您避免常见错误。
如果我是你,我会选择使用C++,即使门槛一开始可能有点高。此外,如果您没有书籍,则需要在该主题下获取一本。尽管无论您使用C还是C ++,COM编程都不是胆小的人所能轻易掌握的东西,网络上有许多示例可供使用,但最好有一些引导您入手。
COM使用的C++仅限于C部分的一个很小的子集,没有要求使用许多“可怕”的项目,例如:
异常 - 如果你没有正确处理异常(需要真正理解RAII习惯,如果你习惯于更传统的C / Win32编程方式,则可能需要一些时间适应),那么在C ++中它们会让你非常困扰;但是异常并不是COM的一部分:COM使用返回代码进行所有错误处理。如果需要,有一些包装器和编译器扩展可以将COM的返回代码转换为C ++异常,但这是可选的。
类层次结构和继承 - 继承实际上也不是COM本身的一部分,除了所有COM接口都派生自(或者说从)IUnknown开始的方法之外。但是您不需要了解任何关于多重虚拟继承的知识来使用 COM。如果您要实现COM对象,则了解其中一些内容非常有用,但仅使用它则不需要。(例如,使用C ++多重继承是实现公开多个接口的COM对象的非常常见的方法,但这不是唯一的方法。)
模板 - 再次强调,不是COM的一部分,但有几个库 - 例如MFC和ATL - 使用模板使COM更加简单易用。特别是对于像CComPtr这样的智能指针类,它将为您处理一些引用计数,使您的代码可以集中精力做真正有趣的事情,而不是被包装在管理性任务中。
因此,不需要在C语言中执行以下操作(通过vtable并显式传递this参数):
pUnk->lpVtbl->SomeMethod(pUnk, 42);
pUnk->SomeMethod(42);
您真的不想在每次进行COM调用时都要键入->lpVtbl,并确保传递正确的“this”参数(复制和粘贴时要小心!),对吗?
我的建议是找一本好的COM书籍 - Inside COM是一本好书 - 然后只需开始使用您熟悉的C ++子集。一旦您知道如何“原始”使用COM指针,并自己使用QI,AddRef等,则可以尝试使用帮助器库,这些库使用模板为您执行一些簿记工作。决定使用将COM错误映射到C ++异常的包装器有点更大的跳跃,因为您需要首先编写异常安全的C ++代码,因此需要了解这些问题的各种问题。但我想不出任何好的理由 - 除了纯粹的好奇心 - 再返回并使用纯C中的COM。
pUnk->lpVtbl
的问题可以通过定义宏来轻松解决,例如 #define OBJ(x) ((x)->lpVtbl)
然后像这样使用 OBJ(pUnk)->SomeMethod(pUnk, 42)
。由于 C 和 C++ 并不是严格的子集-超集关系,因此人们可以根据实际情况选择任何一种语言进行开发;后者并不会在每种情况下都自动替换前者,并且也不一定是线性和无可争议的改进。再加上某个著名厂商的 C/C++ 编译器甚至不支持全部的 C99,这一点更值得注意。 - Armen Michaeli