20

Hope this question isn't going to be too vague. Reading through the COM spec and Don Box's Essential COM book, there is plenty of talk of the "problems that COM solves" - and they all sound important, relevant and current.

So how are the problems that COM addresses dealt with on other systems (linux, unix, OSX, android)? I'm thinking of things like:

  • binary compatibility across compilers and compiler versions
  • binary component reuse
  • compiling an application such that it has run-time dependencies rather than load-time ones (so that it runs even when a dependency is missing)
  • access to library functionality from languages other than the library's own
  • reasonably low-overhead remote procedure calls to components loaded in the address space of a different process
  • etc (I'm sure the list goes on)

I'm basically just trying to understand why for instance on Linux CORBA isn't a thing like COM is a thing on Windows (if that makes any sense). Does maybe software development on Linux subscribe to a different philosophy than the component-based model proposed by COM?

And finally, is COM a C/C++ thing? Several times I've come across comments from people saying COM is made "obsolete" by .NET but without really explaining what they meant by that.

Community
  • 1
  • 1
Maria Boghiu
  • 483
  • 3
  • 9
  • https://en.wikipedia.org/wiki/D-Bus provides a few of the things that COM does (letting one component talk to another) on linux, although in an entirely different way. – jcoder Nov 26 '13 at 13:21

5 Answers5

17

For the remainder of this post, I'm going to use Linux as an example of open-source software. Where I mention "Linux" it's mostly a short/simple way to refer to open source software in general though, not anything specific to Linux.

COM vs. .NET

COM isn't actually restricted to C and C++, and .NET doesn't actually replace COM. However, .NET does provide alternatives to COM for some situations. One common use of COM is to provide controls (ActiveX controls). .NET provides/supports its own protocol for controls that allows somebody to write a control in one .NET language, and use that control from any other .NET language--more or less the same sort of thing that COM provides outside the .NET world.

Likewise, .NET provides Windows Communication Foundation (WCF). WCF implements SOAP (Simple Object Access Protocol)--which may have started out simple, but grew into something a lot less simple at best. In any case, WCF provides many of the same kinds of capabilities as COM does. Although WCF itself is specific to .NET, it implements SOAP, and a SOAP server built using WCF can talk to one implemented without WCF (and vice versa). Since you mention overhead, it's probably worth mentioning that WCF/SOAP tend to add more overhead that COM (I've seen anywhere from nearly equal to about double the overhead, depending on the situation).

Differences in Requirements

For Linux, the first two points tend to have relatively low relevance. Most software is open source, and many users are accustomed to building from source in any case. For such users, binary compatibility/reuse is of little or no consequence (in fact, quite a few users are likely to reject all software that isn't distributed in source code form). Although binaries are commonly distributed (e.g., with apt-get, yum, etc.) they're basically just caching a binary built for a specific system. That is, on Windows you might have a single binary for use on anything from Windows XP up through Windows 10, but if you use apt-get on, say, Ubuntu 18.02, you're installing a binary built specifically for Ubuntu 18.02, not one that tries to be compatible with everything back to Ubuntu 10 (or whatever).

Being able to load and run (with reduced capabilities) when a component is missing is also most often a closed-source problem. Closed source software typically has several versions with varying capabilities to support different prices. It's convenient for the vendor to be able to build one version of the main application, and give varying levels of functionality depending on which other components are supplied/omitted.

That's primarily to support different price levels though. When the software is free, there's only one price and one version: the awesome edition.

Access to library functionality between languages again tends to be based more on source code instead of a binary interface, such as using SWIG to allow use of C or C++ source code from languages like Python and Ruby. Again, COM is basically curing a problem that arises primarily from lack of source code; when using open source software, the problem simply doesn't arise to start with.

Low-overhead RPC to code in other processes again seems to stem primarily from closed source software. When/if you want Microsoft Excel to be able to use some internal "stuff" in, say, Adobe Photoshop, you use COM to let them communicate. That adds run-time overhead and extra complexity, but when one of the pieces of code is owned by Microsoft and the other by Adobe, it's pretty much what you're stuck with.

Source Code Level Sharing

In open source software, however, if project A has some functionality that's useful in project B, what you're likely to see is (at most) a fork of project A to turn that functionality into a library, which is then linked into both the remainder of project A and into Project B, and quite possibly projects C, D, and E as well--all without imposing the overhead of COM, cross-procedure RPC, etc.

Now, don't get me wrong: I'm not trying to act as a spokesperson for open source software, nor to say that closed source is terrible and open source is always dramatically superior. What I am saying is that COM is defined primarily at a binary level, but for open source software, people tend to deal more with source code instead.

Of course SWIG is only one example among several of tools that support cross-language development at a source-code level. While SWIG is widely used, COM is different from it in one rather crucial way: with COM, you define an interface in a single, neutral language, and then generate a set of language bindings (proxies and stubs) that fit that interface. This is rather different from SWIG, where you're matching directly from one source to one target language (e.g., bindings to use a C library from Python).

Binary Communication

There are still cases where it's useful to have at least some capabilities similar to those provided by COM. These have led to open-source systems that resemble COM to a rather greater degree. For example, a number of open-source desktop environments use/implement D-bus. Where COM is mostly an RPC kind of thing, D-bus is mostly an agreed-upon way of sending messages between components.

D-bus does, however, specify things it calls objects. Its objects can have methods, to which you can send signals. Although D-bus itself defines this primarily in terms of a messaging protocol, it's fairly trivial to write proxy objects that make invoking a method on a remote object look pretty much like invoking one on a local object. The big difference is that COM has a "compiler" that can take a specification of the protocol, and automatically generate those proxies for you (and corresponding stubs in the far end to receive the message, and invoke the proper function based on the message it received). That's not part of D-bus itself, but people have written tools to take (for example) an interface specification and automatically generate proxies/stubs from that specification.

As such, although the two aren't exactly identical, there's enough similarity that D-bus can be (and often is) used for many of the same sorts of things as COM.

Systems Similar to DCOM

COM also allows you to build distributed systems using DCOM (Distributed COM). That is, a system where you invoke a method on one machine, but (at least potentially) execute that invoked method on another machine. This adds more overhead, but since (as pointed out above with respect to D-bus) RPC is basically communication with proxies/stubs attached to the ends, it's pretty easy to do the same thing in a distributed fashion. The difference in overhead, however, tends to lead to differences in how systems need to be designed to work well, though, so the practical advantage of using exactly the same system for distributed systems as local systems tends to be fairly minimal.

As such, the open source world provides tools for doing distributed RPC, but doesn't usually work hard at making them look the same as non-distributed systems. CORBA is well known, but generally viewed as large and complex, so (at least in my experience) current use is fairly minimal. Apache Thrift provides some of the same general type of capabilities, but in a rather simpler, lighter-weight fashion. In particular, where CORBA attempts to provide a complete set of tools for distributed computing (complete with everything from authentication to distributed time keeping), Thrift follows the Unix philosophy much more closely, attempting to meet exactly one need: generate proxies and stubs from an interface definition (written in a neutral language). If you want to do those CORBA-like things with Thrift you undoubtedly can, but in a more typical case of building internal infrastructure where the caller and callee trust each other, you can avoid a lot of overhead and just get on with the business at hand. Likewise, google RPC provides roughly the same sorts of capabilities as Thrift.

OS X Specific

Cocoa provides distributed objects that are fairly similar to COM. This is based on Objective-C though, and I believe it's now deprecated.

Apple also offers XPC. XPC is more about inter-process communication than RPC, so I'd consider it more directly comparable to D-bus than to COM. But, much like D-bus, it has a lot of the same basic capabilities as COM, but in different form that places more emphasis on communication, and less on making things look like local function calls (and many now prefer messaging to RPC anyway).

Summary

Open source software has enough different factors in its design that there's less demand for something providing the same mix of capabilities as Microsoft's COM provides on Windows. COM is largely a single tool that tries to meet all needs. In the open-source world, there's less drive to provide that single, all-encompassing solution, and more tendency toward a kit of tools, each doing one thing well, that can be put together into a solution for a specific need.

Being more commercially oriented, Apple OS X probably has what are (at least arguably) closer analogs to COM than most of the more purely open-source world.

Community
  • 1
  • 1
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • Interesting perspective. – Len Holgate Nov 26 '13 at 11:46
  • 6
    The advantage of a shared standard like COM over things like SWIG and JNI is that it's an O(N) solution instead of an O(N*N) solution, given N languages. (That's actually unrelated to source vs binary) – MSalters Nov 26 '13 at 12:07
  • That's really interesting, the whole open/closed source aspect wasn't mentioned in any of the COM reading I've done so far and it makes a lot of sense. Still, it isn't uncommon (is it?) to have a binary with load-time dependencies on shared objects it expects to find (already compiled) on your system (in /lib or /usr/lib), even when you compile the project itself from source. Running ldd on an executable might show it depends on things like libc.so, libtinfo.so, libdl.so, libpthread.so etc. Would there not be linking problems if the version of your compiler was incompatible? – Maria Boghiu Nov 26 '13 at 12:35
  • Sorry, reached comment character limit - basically if the compiler you use to compile your application is somehow incompatible with the compiler that was used to create e.g. libc or libpthread or something, wouldn't you run into problems? Hope the question makes sense.. – Maria Boghiu Nov 26 '13 at 12:39
  • @shanba_kay: Yes, it's entirely possible to see incompatibilities between an executable and a shared object. Again, however, this is ameliorated by using open-source: you receive source code, and build the application on the target machine, so it links against exactly the SOs already on that machine. In a typical case, you might use the *same* compiler to build nearly everything on the machine. That's kind of brute-forcish, but still effective at ensuring compiler compatibility. – Jerry Coffin Nov 26 '13 at 16:39
  • @MSalters: It's certainly true that a neutral format reduces an O(N*N) problem to an O(N) problem. The simple fact is, however, that few enough languages are in really common use that for *most* people it's irrelevant. If you had hundreds of languages in wide use, O(N) vs. O(N*N) would be a huge win. A handful of languages accounting for the *vast* majority of development makes it a small win at best. – Jerry Coffin Nov 26 '13 at 16:50
  • 1
    It's worth pointing out that the "neutral" format used for COM interfaces happens to be the layout of a virtual function table produced by a Microsoft C++ compiler (with a particular set of compiler options and directives). While it is/was possible to create and use COM components with other tools, COM can be seen as a way to get C++ code to interoperate with higher-level languages in a similar way to using C bindings. If you aren't trying to mix C++ with other languages, COM isn't a natural fit. – Kristopher Johnson Nov 26 '13 at 19:12
  • @JerryCoffin: so does a Linux distro's package manager effectively provide a solution to the binary compatibility problem? i'm trying to understand why Windows doesn't just have a package manager - and when an app needs a binary component it fetches it from a known repository where everything is known to be compiled in a compatible fashion? – Maria Boghiu Nov 26 '13 at 20:14
  • @shanba_kay: Most Linux packages are distributed as source code. The package manager doesn't really cure binary compatibility problems, but compiling everything on the target system (mostly) does. – Jerry Coffin Nov 26 '13 at 23:09
  • @Kristopher COM has nothing to do with C++. COM is C. The fact that Microsoft's C++ compiler can produce COM objects is an artifact. COM is also certainly not a way to interface C++ with higher-level languages. COM doesn't support C++ exceptions, for example. – IInspectable Nov 28 '13 at 22:46
  • The killer feature of COM is *compatibility*. You may not need binary compatibility in open source but you certainly need stable interfaces, if you don't want to have to rewrite (and retest!) large pieces of functionality when you integrate software across teams. The procedure you mention, extracting a new library, provides the opposite of that. – Jørgen Fogh Nov 18 '15 at 22:55
  • On a different note, COM gives you *the option* of using RPC but a key feature the design is that it does not require you too. Once you have instantiated an object, method calls are just normal virtual calls and do not require marshaling. If virtual calls are the bottle neck of your application, you're doing it wrong. – Jørgen Fogh Nov 18 '15 at 22:58
  • @JørgenFogh: There certainly *are* times you need stable interfaces in open source, and when you do, you typically end up with something reasonably similar to COM, such as Apache Thrift or Google RPC. You can also define a binary-level interface in terms of messages exchanged, without having the marshaling/serialization (and such) that RPC provides (e.g., Sun XDR or Google Protocol buffers). – Jerry Coffin Nov 18 '15 at 23:01
6

A quick answer on the last question: COM is far from being obsolete. Almost everything in the Microsoft world is COM-based, including the .NET engine (the CLR), and including the new Windows 8.x's Windows Runtime.

Here is what Microsoft says about .NET in it latest C++ pages Welcome Back to C++ (Modern C++):

C++ is experiencing a renaissance because power is king again. Languages like Java and C# are good when programmer productivity is important, but they show their limitations when power and performance are paramount. For high efficiency and power, especially on devices that have limited hardware, nothing beats modern C++.

PS: which is a bit of a shock for a developer who has invested more than 10 years on .NET :-)

Community
  • 1
  • 1
Simon Mourier
  • 132,049
  • 21
  • 248
  • 298
  • 1
    re: c++ is back - yes, that seemed to be pretty much the theme at this year's C++ and Beyond conference. glad, too - i really like c++; re: COM not being obsolete - yes, see, that's *exactly* what i thought had to be the case, but searching for "component object model" yields surprisingly few results that aren't MSDN or some university course PDF; searching for something more specific, like "register com object" is even less fruitful, and limiting your searches to the past year basically yields no results; so i was intrigued: why isn't the internet talking about COM? hence the question.. – Maria Boghiu Nov 26 '13 at 19:08
  • The thing is, in the Microsoft world, .NET was the standard for most development for the last 10 years or so, and although COM was always still there undercover, it was not really visible. Managed C++ or C++/CLI never got the same success as C# either (partly because they were Microsoft specific extensions) and the interop (P/Invoke, COM or not) capabilities of the CLR are really good. Indeed, in Windows 8.x's Windows Runtime, it's still not very visible since there is a projection/binding system for most languages, including javascript. – Simon Mourier Nov 26 '13 at 20:29
  • Your first two sentences contract one another. Did you mean "far from obsolete" (i.e. not obsolete at all) rather than "all but obsolete" (i.e. not completely obsolete but very nearly)? – Harry Johnston Nov 26 '13 at 22:38
  • @HarryJohnston - hmmm... I meant not obsolete at all. I'm not native English speaking, so I updated the answer :-) (PS: don't forget to use the @ in comments, I just happened to pass by here and only saw your comment today). – Simon Mourier Dec 04 '13 at 14:53
  • @SimonMourier: odd; it was my understanding that users are notified of all comments on their own answers. At least, it works that way for me. – Harry Johnston Dec 04 '13 at 21:39
4

In the Linux world, it is more common to develop components that are statically linked, or which run in separate processes and communicate by piping text (maybe JSON or XML) back and forth.

Some of this is due to tradition. UNIX developers have been doing stuff like this long before CORBA or COM existed. It's "the UNIX way".

As Jerry Coffin says in his answer, when you have the source code for everything, binary interfaces are not as important, and in fact just make everything more difficult.

COM was invented back when personal computers were a lot slower than they are today. In those days, loading components into your app's process space and invoking native code was often necessary to achieve reasonable performance. Now, parsing text and running interpreted scripts aren't things to be afraid of.

CORBA never really caught on in the open-source world because the initial implementations were proprietary and expensive, and by the time high-quality free implementations were available, the spec was so complicated that nobody wanted to use it if they weren't required to do so.

Kristopher Johnson
  • 81,409
  • 55
  • 245
  • 302
  • Thanks. Curious though regarding what you say about computers being a lot faster now so not needing to load components in an app's process space for performance reasons - would the problem of performance not still be relevant (and maybe even more so) for mobile devices with limited RAM? or where saving CPU cycles (by running native code) might help save battery life? – Maria Boghiu Nov 26 '13 at 12:43
  • Even a cheap smartphone is many times more powerful than a 1990's-era PC. Using native code is still important in some applications (3D games, for example), but dynamic loading of components from multiple vendors isn't common in such apps. Android apps run on a virtual machine; iOS apps use an object-oriented runtime. Many smartphone apps are actually just web-page views with HTML/CSS-based UIs running Javascript code. – Kristopher Johnson Nov 26 '13 at 14:25
3

To a large extent, the problems solved by COM are simply ignored on Linux.

It is true that binary compatibility is less important when you have the source code available. However, you still have to worry about modularisation and versioning. If two different programs depend on different versions of the same library, you need to somehow support that.

Then there is the case of the same program using different versions of the same library. This is often useful when working on large legacy programs, where upgrading everything can be prohibitively expensive but you would like to use new features anyway. With COM, the old parts of the program can just be left alone, since new library versions can more easily be made backwards compatible.

In addition, having to compile from source instead of binary compatibility is a huge hassle. Especially if you are actually developing software, since binary incompatibility means you have to recompile much more often. If one tiny part changes in a large C++ program, you may have to wait for a 30 minute recompile. If the different pieces are compatible, only the part which changed has to be recompiled.

Jørgen Fogh
  • 7,516
  • 2
  • 36
  • 46
0

COM and DCOM in particular have been around in windows for some considerable time now and naturally windows developers have made use of this powerful framework.

We are now in the cross platform age and when porting such applications to other platforms we are faced with challenges which in many cases can be mitigated or eliminated altogether unless the application we are porting is more than just one simple standalone app.

If your dealing with a whole suite of modules running on different machines all communicating using windows specific technologies such as DCE/RPC, DCOM or even windows named pipes then your job just became an order of magnitude harder.

DCE/RPC DCOM and windows named pipes all are very windows specific, non portable and of course subject to windows security access control.

For instance anyone familar with OPC DA (an industrial automation protocol based on DCOM still very much in use but now superceded by OPC UA (which avoids DCOM))) will know that there are no elegant solutions here if the client (or server) needs to be available for Linux!!

Sure there appear to be some technical hurdles here given that the MS code is not in the public domain but projects such as Wine have a partly ok DCE/RPC implementation and MS do publish some of the protocol docs. Try searching and you will probably find little information and few products open source or otherwise to help you.

Perhaps the lack of open source or affordable options here is more due to legal concerns - I wonder!

Some simpler solutions simply involve installing a "gateway service" on the windows machines to allow an alternative means of access to DCOM interfaces on that machine. This is fine if the windows machine does not belong to an unwilling 3rd party which unfortunately is sometimes the case!!! I know we'll just chuck another Windows machine as the gateway in the middle is the usual global warming enhancing solution to that problem.

I would conclude that Linux to Windows DCOM interoperability is certainly not impossible but it does appear to be a topic that few are interested in talking about unless you get your wallet out!