简体   繁体   English

纯C中的Win32 COM编程

[英]Win32 COM Programming in Pure C

I have a programming project which requires access to some of the lower-level Windows APIs (WASAPI, in particular). 我有一个编程项目,需要访问一些较低级别的Windows API(特别是WASAPI)。 I am fairly experienced with higher-level programming languages such as C#, Java, and PHP, and I know only a little bit about C/C++. 我对C#,Java和PHP等高级编程语言很有经验,而且我对C / C ++只有一点了解。

I would like to use C (not C++) for this project, as C++ is kind of scary . 我想在这个项目中使用C(而不是C ++),因为C ++有点可怕 Upon changing the C/C++ settings of my project in Visual Studio to compile as C code, I noticed that any calls to __uuidof won't work, as they are C++ specific. 在Visual Studio中将我的项目的C / C ++设置更改为编译为C代码后,我注意到对__uuidof任何调用都不起作用,因为它们是特定于C ++的。

My question is twofold: 我的问题是双重的:

  1. Is it possible to write Win32 programs that utilize COM in pure C , and 是否可以编写在纯C中使用COM的Win32程序
  2. If so, should using pure C be avoided? 如果是这样,应该避免使用纯C吗?
  1. Yes it is possible to use write pure C programs that utilize COM, in fact that was common practice 10-15 years ago. 是的,可以使用使用COM的写纯C程序,事实上这是10 - 15年前的常见做法。

  2. You are not doing yourself a favor by using C (as you already have noticed). 你不是通过使用C做自己的帮助(正如你已经注意到的那样)。 Eg ATL provides lots of help when you are doing COM and can help you to avoid common mistakes. 例如,ATL在您做COM时提供了很多帮助,可以帮助您避免常见错误。

If I were you I would go the C++ even if the threshold may be a bit higher at first. 如果我是你,我会去C ++,即使最初的门槛可能稍微高一点。 Also get a book in the subject if you do not have one. 如果您没有该书,也可以获得该主题的书籍。 There are lots of examples to be found in the net but it is good to have something that leads you by the hand since COM programming is not for the faint of heart, regardless whether you use C or C++. 在网络中有很多例子,但是有一些东西可以引导你,因为COM编程不适合胆小者,无论你使用的是C还是C ++。

COM uses a pretty small subset of C++ beyond the C part, and there's no requirement to use many of the 'scary' items such as: COM在C部分之外使用了相当小的C ++子集,并且不需要使用许多“可怕”项目,例如:

  • Exceptions - these can really bite you in C++ if you don't get them right (you need to really buy into the RAII idiom, which can take getting used to if you're used to more traditional C/Win32 coding); 例外 - 如果你没有正确使用它们,这些可以真正咬你C ++(你需要真正购买RAII成语,如果你习惯了更传统的C / Win32编码,它可能会习惯); but exceptions are not part of COM at all: COM uses return codes for all error handling. 但异常根本不是COM的一部分:COM使用返回代码进行所有错误处理。 There are some wrappers and compiler extensions that will convert COM's return codes into C++ exceptions if you want, but it's opt-in. 有一些包装器和编译器扩展,如果你愿意,可以将COM的返回代码转换为C ++异常,但它是选择加入的。

  • Class hierarchies and inheritance - Inheritance is also not really part of COM itself, other than the fact that all COM interfaces derive from (or, start off with the methods from) IUnknown. 类层次结构和继承 - 继承也不是COM本身的一部分,除了所有COM接口派生自(或从IKnknown方法开始)的事实。 But you don't need to know anything about multiple virtual inheritance to use COM. 但是,您不需要了解有关使用 COM的多个虚拟继承的任何信息。 Some of this is very useful to know if you are implementing COM objects yourself, but not to just use it. 其中一些对于了解您是否自己实现 COM对象非常有用,而不是仅仅使用它。 (For example, using C++ multiple inheritance is a very common way to implement a COM object that exposes multiple interfaces; but it's not the only way.) (例如,使用C ++多重继承是实现暴露多个接口的COM对象的一种非常常见的方式;但它不是唯一的方法。)

  • Templates - again, not part of COM, but there are several libraries - eg. 模板 - 再次,不是COM的一部分,但有几个库 - 例如。 MFC and ATL - that use templates to make COM a lot simpler to use. MFC和ATL - 使用模板使COM更易于使用。 This is especially true for smart pointer classes like CComPtr that will take care of some reference counting for you, allowing your code to concentrate on doing the real interesting stuff instead of having it packed with housekeeping stuff. 对于像CComPtr这样的智能指针类来说尤其如此,它将为您处理一些引用计数,允许您的代码专注于做真正有趣的事情,而不是让它包含管家的东西。

The main link between COM and C++ is all C++ compilers on Windows will lay out a C++ object in memory in a way that matches exactly what COM requires. COM和C ++之间的主要联系是Windows上的所有C ++编译器都会以与COM所需内容完全匹配的方式在内存中布局C ++对象。 This allows you to use a COM object as though it were a C++ object, which makes the code considerably less verbose, as the language/compiler is taking care of some really simple but verbose stuff for you. 这允许您使用COM对象,就像它是一个C ++对象一样,这使得代码相当简洁,因为语言/编译器会为您处理一些非常简单但冗长的内容。

So instead of doing the following in C (step through vtable and pass this param explicitly): 所以不要在C中执行以下操作(逐步执行vtable并明确传递此参数):

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

You can do the following in C++: 您可以在C ++中执行以下操作:

pUnk->SomeMethod(42);

You really don't want to have to type ->lpVtbl and make sure you pass the correct 'this' parameter (be careful when cutting and pasting!) with every single COM call you make, do you? 你真的不想输入 - > lpVtbl并确保你通过每个COM调用传递正确的'this'参数(切割和粘贴时要小心!),对吗?

My suggestion would be to find a good COM book - Inside COM is a good one - and just start off using the C++ subset that you are comfortable with. 我的建议是找到一本好的COM书 - 里面的COM是一个很好的 - 然后开始使用你熟悉的C ++子集。 Once you know how to use a COM pointer "raw", and use QI, AddRef and so on yourself, then perhaps you can play with the helper libraries that use templates to do some of the bookkeeping for you. 一旦你知道如何使用COM指针“raw”,并自己使用QI,AddRef等,那么也许你可以使用帮助库来使用模板为你做一些簿记。 Deciding to use wrappers that map COM errors to C++ exceptions is a bit of a bigger jump, as you need to write C++ code that is exception-safe first so need to understand the various issues with those first. 决定使用将COM错误映射到C ++异常的包装器是一个更大的跳跃,因为您需要首先编写异常安全的C ++代码,因此需要首先了解这些问题。 But I can't think of any good reason - other than sheer curiosity - for going back and using COM from plain C. 但我想不出任何好的理由 - 除了纯粹的好奇心 - 回归并使用来自普通C的COM。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM