5 ms·
COM (Component Object Model) is compatible with C. It's still obviously C++ code being shoehorned into C by explicitly declaring the layout of the object (VTab
by Dwedit 4y ago
COM (Component Object Model) is compatible with C. It's still obviously C++ code being shoehorned into C by explicitly declaring the layout of the object (VTable member), but it does work. You get inheritance that way, and inter-module compatible cleanup. The downside is so much boilerplate code to declare the object, and the performance cost of virtual calls.
You don't necessarily need the complete COM system. For example, you could remove use of the Windows Registry, use of IDL files, remove the `QueryInterface` method, remove the use of GUIDs, remove the class factories (when just a simple 'create' function would do), remove Windows API functions related to cross-module memory management (not using `CoTaskAlloc`). Then it would be portable to systems that aren't Windows. One thing you can't remove is specifying a calling convention for the class methods, because C++ `__thiscall` is not compatible with C code on Windows.
- morelisp 4y agoThis is basically what the author is referring to with GObject.
- pavlov 4y ago> “Then it would be portable to systems that aren't Windows” I’ve seen this type of “COM Lite” used for cross-platform plugin and driver APIs. For example Blackmagic Design, a manufacturer of pro video capture hardware, provides an SDK that is essentially identical on Windows, Linux and Mac using this design.
- spacechild1 4y agoAnother example would be the VST3 SDK.
- kelnos 4y agoThis is more or less what GObject is, which the author mentions in passing. It's an OO system for C, but it does require quite a lot of boilerplate, and you need to manually initialize vtables when creating new subclasses. You also need to manually chain up to the superclass in virtual methods, in many places where it's easy to forget. It's a decent system, all things considered, but it's just a reminder that C's type system is very weak and implementing advanced features all but requires abuse of the preprocessor to avoid unreadable code.
- Dwedit 4y agoWhile you do need to manually initialize a vtable pointer, that pointer can simply point to a const struct which lives in the read-only data section. You don't need to allocate a new vtable with each object or anything like that. And you can do COM objects in C without using the preprocessor at all (outside of the "are we C++ or not" condition, then you could use real classes instead)
- rzzzt 4y agoCan you emulate partial function application somehow in C or does the caller still need to supply "this" as an argument to instance methods?
- ablob 4y agoYou can emulate partial function application. You also always need to supply some kind of "this" if you don't want your data to live in static memory.
- wruza 4y agoGObject doesn’t abuse the preprocessor. It suggests to #define type-guard parts of the standard boilerplate (purely in spirit of C), but doesn’t require you to do so. Everything else is just C. Also, being an object system, not only a type system, it is more advanced than C++ in parts of properties and signals. Of course that requires some cooking. For example, Qt had to resort to a custom pre-compiler for that. That said, I believe it loses quickly in ergonomics to plain Objective C, which is best “practical C + objects” flavor ever done, imo.
- pjmlp 4y agoDepending on how much one likes to type @.
- asveikau 4y agoI think Mozilla has historically had a lot of COM outside of Windows. But there's been a goal to remove it: https://wiki.mozilla.org/Gecko:DeCOMtamination https://wiki.mozilla.org/Gecko:DeCOMtamination I believe VirtualBox is another project with COM on other platforms. I see lots of GUIDs and HRESULTs in their error messages. I actually really like the COM style when done well. HRESULT, the idea of somewhat standardized error handling that sub-divides the space of a 32-bit integer into various subsystem-specific error codes, is one of my favorite ideas from there. Some things are not so nice. For example, everything being a virtual call is not good for performance. Reference counting is also great but over-use of it is also not great for performance (for example, in C++ it's considered poor form to make everything std::shared_ptr<> when you can get away with less).
- Dwedit 4y agoThe goal to remove it applied to internal use, for things which aren't exported. Which makes perfect sense, COM-like interfaces are only needed when you cross module boundaries, and need an fixed ABI.
- asveikau 4y agoI find when you get in the groove of the COM style, especially its consistent error handling, you want to use it within modules too. But I think part of their objections for within a module (from memory, because I haven't looked into their rationale in a while) is it's not worth the performance cost.
- lmz 4y agoIt's been reimplemented multiple times. Besides Mozilla's XPCOM there's also StarOffice/OpenOffice.org/LibreOffice's UNO.
- mkoubaa 4y agoMy company has at least 3 implementations of cross platform COM (one organic, the rest through acquisitions)
- pjmlp 4y agoI like COM, as an idea, however besides VB 6 and C++/CX, its tooling has always been clunky at best. On .NET, the way RCW/CCW works requires understanding both .NET and C++, in other to get it right, and now they decided to also have another way of accessing COM from .NET since CsWinRT was introduced, with quite a bit of boilerplate as well. The we have the developer groups always keen in pushing ATL, WRL and now C++/WinRT, all with the boilerplate, and after 20 years, still no good VS tooling for IDL files or code generation. By the way, registration free COM is a thing since Windows XP, when application manifests were introduced. It is quite ironic that the competition (Borland originally) always had much better tooling to deal with COM, than WinDev is willing to offer to their own developer community. The way IO and Driver Kit work on macOS/iOS is also COM like.
- Dwedit 4y agoI haven't really tried out registration free COM yet, I just load the DLLs, instantiate the factory, then instantiate the object. You can totally do that. DLLs export `DllGetClassObject`, you call that with the GUID you want, and `IID_IClassFactory`, then you get a factory object. Then you call `CreateInstance` from the factory object, and you have your COM object. Useful for Video Codecs and manually building DirectShow filter graphs. Works whether the codec is properly installed or not.