【问题标题】:Win32 COM Programming in Pure C纯 C 中的 Win32 COM 编程
【发布时间】:2013-01-22 14:11:53
【问题描述】:

我有一个编程项目,它需要访问一些较低级别的 Windows API(尤其是 WASAPI)。我对 C#、Java 和 PHP 等高级编程语言相当有经验,而且我对 C/C++ 知之甚少。

我想在这个项目中使用 C(不是 C++),如 C++ is kind of scary。在 Visual Studio 中更改我的项目的 C/C++ 设置以编译为 C 代码后,我注意到对 __uuidof 的任何调用都不起作用,因为它们是 C++ 特定的。

我的问题有两个:

  1. 是否可以用纯 C 语言编写使用 COM 的 Win32 程序,以及
  2. 如果是这样,是否应该避免使用纯 C?

【问题讨论】:

  • 当然有可能,但是您可以获得更多 C++ 的内置支持。如果我没记错的话(我不再有这本书了),Dale Rogerson 的“Inside COM”从 COM 的基础开始接近 COM——解释了如何从直接 C 中访问它。
  • 是的,是的(恕我直言)。在 20 年的 COM 编程中,我从未听到有人说他们更喜欢使用 C,因为 C++ COM 编程是“可怕的”。我已经做了 long 时间。 C ++要容易得多。您可以在 C 中做到这一点,但您希望您一旦学习了 C++ 中最基本的实现就没有。 (为了添加到 Michael 的书单中,将时间拉回到 Kraig Brockschmidt 的 Inside OLE2 =P)。
  • 请参阅previous question 了解有关 FQA 的信息。简短的总结:不要让它把你吓跑 C++;大部分都是废话。

标签: c winapi com


【解决方案1】:
  1. 是的,可以使用编写使用 COM 的纯 C 程序,事实上这在 10 到 15 年前是常见的做法。

  2. 使用 C 并不是在帮自己一个忙(正如您已经注意到的那样)。例如。 ATL 在你做 COM 时提供了很多帮助,可以帮助你避免常见的错误。

如果我是你,我会选择 C++,即使一开始的门槛可能会更高一些。如果你没有这方面的书,也可以买一本。在网上可以找到很多示例,但最好有一些可以指导您的东西,因为无论您使用 C 还是 C++,COM 编程都不适合胆小的人。

【讨论】:

    【解决方案2】:

    COM 在 C 部分之外使用了相当小的 C++ 子集,并且不需要使用许多“可怕”的项目,例如:

    • 例外 - 如果你没有正确理解它们,这些可能会在 C++ 中真正咬你(你需要真正购买 RAII 成语,如果你习惯了更传统的习惯,可能需要习惯C/Win32 编码);但异常根本不是 COM 的一部分:COM 使用返回码进行所有错误处理。如果需要,有一些包装器和编译器扩展可以将 COM 的返回代码转换为 C++ 异常,但它是可选的。

    • 类层次结构和继承 - 继承实际上也不是 COM 本身的一部分,除了所有 COM 接口都派生自(或从方法开始)IUnknown 的事实。但是您不需要了解任何关于多重虚拟继承的知识就可以使用 COM。其中一些对于了解您是否自己实现 COM 对象非常有用,但不仅仅是使用它。 (例如,使用 C++ 多重继承是实现公开多个接口的 COM 对象的一种非常常见的方法;但这不是唯一的方法。)

    • 模板 - 同样,不是 COM 的一部分,但有几个库 - 例如。 MFC 和 ATL - 使用模板使 COM 更易于使用。对于像 CComPtr 这样的智能指针类来说尤其如此,它会为你处理一些引用计数,让你的代码专注于做真正有趣的事情,而不是把它打包成家务。

    COM 和 C++ 之间的主要联系是 Windows 上的所有 C++ 编译器都会以完全符合 COM 要求的方式在内存中布置 C++ 对象。这使您可以像使用 C++ 对象一样使用 COM 对象,这使代码的冗长程度大大降低,因为语言/编译器正在为您处理一些非常简单但冗长的内容。

    因此,不要在 C 中执行以下操作(单步执行 vtable 并显式传递此参数):

    pUnk->lpVtbl->SomeMethod(pUnk, 42);
    

    您可以在 C++ 中执行以下操作:

    pUnk->SomeMethod(42);
    

    您真的不想在每次调用 COM 时都输入 ->lpVtbl 并确保传递正确的“this”参数(剪切和粘贴时要小心!),对吗?

    我的建议是找一本好的 COM 书——《Inside COM》是一本好书——然后开始使用你熟悉的 C++ 子集。一旦您知道如何使用“原始” COM 指针,并自己使用 QI、AddRef 等,那么也许您可以使用使用模板为您做一些簿记的帮助程序库。决定使用将 COM 错误映射到 C++ 异常的包装器是一个更大的跳跃,因为您需要首先编写异常安全的 C++ 代码,因此需要首先了解这些问题的各种问题。但我想不出任何好的理由——除了纯粹的好奇心——回去使用纯 C 语言的 COM。

    【讨论】:

    • 我想说,编写 C 时必须编写 pUnk->lpVtbl 的麻烦可以通过定义像 #define OBJ(x) ((x)->lpVtbl) 这样的宏然后像 OBJ(pUnk)->SomeMethod(pUnk, 42) 这样使用它来轻松缓解。由于 C 和 C++ 并不是真正处于严格的子集-超集关系中,因此人们仍然可以选择其中任何一个来完成工作,这一切都取决于;后者不会在任何情况下都自动取代前者,也不一定是对它的线性和无可争议的改进。再加上一个已知供应商的某个 C/C++ 编译器甚至不支持所有 C99 的事实。
    猜你喜欢
    • 1970-01-01
    • 2013-07-01
    • 1970-01-01
    • 2011-02-25
    • 1970-01-01
    • 1970-01-01
    • 2011-05-26
    • 2011-03-24
    • 2011-11-15
    相关资源
    最近更新 更多