4 ms·
I'm serious (even if it may not sound like it). COM is a fantastic platform, because it provides simple and efficient interoperability between language runtimes
by fauigerzigerk 7y ago
I'm serious (even if it may not sound like it). COM is a fantastic platform, because it provides simple and efficient interoperability between language runtimes.
But code written for tracing GCs cannot be automatically transformed into COM's (or any) reference counting scheme. And that's why we have this endless tug of war between those who want to build on top of COM versus those who want to build on top of .NET.
It's not just a Microsoft problem either. Our industry has been wasting a ton of resources on duplicating everything for a bunch of different languages/runtimes and it's all either because of GC incompatibility or license incompatibility.
It's not a minor problem even if there are more important problems in the grand scheme of things is what I'm saying.
- vbezhenar 7y agoMay be I don't understand something, but how does it differ from e.g. operating file handles? For example in Java you're supposed to use try-finally to close file handle. You should do the same with reference-counted objects, just manage their lifetime manually. And finalizers will close it for you if you forgot to do that (that should be considered as a bug, but not very serious).
- fauigerzigerk 7y agoIt doesn't differ from that, but in languages that assume the presence of a tracing GC, that pattern is only used for resources other than memory. And therefore you can't (as far as I know anyway) compile arbitrary C#/Java/JavaScript libraries down to reference counted COM in order to make those libraries available to C++ or Rust code.
- pjmlp 7y agoYou can also use that pattern for memory management in .NET. For example stack allocations and unmanaged memory handles. .NET COM interop take care of exposing .NET classes to other COM aware languages. https://docs.microsoft.com/en-us/dotnet/standard/native-interop/cominterop https://docs.microsoft.com/en-us/dotnet/standard/native-inte...
- fauigerzigerk 7y agoYou can, but in order to translate arbitrary .NET code into reference counted COM you would need a guarantee that _all_ code is written like that or that you can statically infer the correct reference counting for _all_ code that isn't written like that.
- youdontknowtho 7y agoI haven't seen the reluctance to use the runtime in interop scenarios. Is this just a personal interest or do you have a particular use case? I'm genuinely interested.
- fauigerzigerk 7y agoThis debate is about Microsoft's decision some 14 years ago to build Windows userland components on top of C++ COM technology instead of .NET as some within Microsoft had wanted. Those inside Microsoft who didn't want to force everyone to use a rather heavyweight runtime including a tracing GC won the debate. It would have affected almost everyone, not just those with use cases that can tolerate the significant additional resource usage. I merely made the observation that the difficulty to infer correct reference counting information from C#/Java code is what caused this rift and a lot of unproductive duplicated effort in our industry.
- youdontknowtho 7y agoI see what you mean. Good point. Cheers.
- vbezhenar 7y agoOfftopic, but I think that Rust memory model makes a perfect consumer of COM services :) May be it'll be integrated to other languages as an additional type system.
- Const-me 7y agoI’ve been writing C++ COM objects for use in .NET for years now. Some are for performance-critical parts, like manually vectorized SIMD code. Another use case is interop heavy code, using Direct3D, media foundation, Eigen, other C and C++ libraries. It works even on Linux https://github.com/Const-me/ComLightInterop https://github.com/Const-me/ComLightInterop I also have these parts, especially about the interop. Libraries like drm, kms, gles, udev, and many other kernel APIs are only usable from C or C++. Had very few issues with IUnknown-based interop. On Linux, my interop library retains .NET objects with GCHandle while they are referenced by C++ code. On Windows, it’s done automatically by the runtime. C++ implemented objects are automatically retained on both OSes. What exactly do you think is a hard problem about such interop? Leaks due to ref.count cycles are possible, but I’m not sure it’s such a huge deal. There’re many good reasons to keep interop API surface small, with obvious “who owns what” relations.
- fauigerzigerk 7y ago>What exactly do you think is a hard problem about such interop? The problem is that .NET libraries cannot be used from C++ or Rust without depending on the entire .NET runtime, including its tracing GC, which is obviously extremely undesirable. And that is probably why Microsoft dropped their plans to write Windows userland components in .NET and decided to write them in C++ instead (exposing COM interfaces). As I see it, the key theoretical issue is that neither CIL nor arbitrary code written in languages like C#, Java, JavaScript or Python contains enough static information to generate purely reference counted code. You're seeing the same on Unix. All truly reusable code is written in languages that don't require a tracing GC. Everything that is written in other languages is duplicated for each language/runtime environment.
- Const-me 7y ago> cannot be used from C++ or Rust without depending on the entire .NET runtime You can compile .NET into native code if you want: MS .net native, Unity’s IL2CPP, etc. These aren’t some research projects, every Unity3D game shipped on iOS compiles with IL2CPP, most windows store apps are built with .net native. The GC probably still included in the output binary somewhere, but it does much less work than usually. > which is obviously extremely undesirable Depends on use case. You wouldn’t want to bring the runtime for a small dependency, but for a large and complex one, like PDF writer or embedded web server, it can be OK. The 2.2 runtime binaries are 25-28MB depending on the platform, not a huge deal. These days, people bring 150MB+ Electron dependency just to render a few strings and colored rectangles :-) > the key theoretical issue is that neither CIL nor arbitrary code written in languages like C#, Java, JavaScript or Python contains enough static information to generate purely reference counted code. C# and Java and strongly typed, have a lot of static information. I think the main reason why it’s impossible to reliably recompile these languages into non-gc code — circular references.