C++ COM C# Mixed Mode Interoperation - c#

I'm trying to understand my options for calling a C# library implementation from unmanaged C++.
My top level module is an unmanaged C++ COM/ATL dll. I would like to integrate functionality of an existing managed C# dll. I have, and can recompile the source for both libraries.
I understand from reading articles like this overview on MSDN and this SO question that it might be possible to create a "mixed-mode" dll which allows the native C++ code to call into the C# library.
I have a couple of questions about this approach:
How do I go about setting this up?
Can I simply change some properties
on the existing COM/ATL project to
allow use of the C# modules?
How will these mixed-mode calls
differ in performance from COM interop
calls? Is there a common string
format that may be used to prevent
conversion or deep copies between
the modules?
If this dll is created
mixed-mode, can it still be
interfaced/used in the same way by
its COM clients, or do they need to
be mixed mode aware?
Will inclusion of the CLR impose substantial
overhead when loading this COM object?
I'm new to Windows development, so please comment if anything in the question statement needs clarification or correction.
Thanks in advance.

How do I go about setting this up? Can I simply change some properties on the existing COM/ATL project to allow use of the C# modules?
If you fully control that project, so changing such settings isn't an issue, then sure. All you need is to enable /clr for this project (In project properties, open the "General" page, and look for "Common Language Runtime" support). Now you can use managed handles (^) and other C++/CLI bits in your project as needed. All existing code written in plain C++ should just keep working (it will be compiled to MSIL now, inasmuch as possible, but its semantics will remain unchanged).
How will these mixed-mode calls differ in performance from COM interop calls? Is there a common string format that may be used to prevent conversion or deep copies between the modules?
A mixed-mode call will be faster, because it uses faster calling conventions, and doesn't do any marshaling the way COM interop does (you either use types that are inherently compatible, or do your own explicit conversions).
There's no common string format - the problem is that System::String both allocates and owns its buffer, and also requires it to be immutable; so you can't create a buffer yourself and then wrap it as String, or create a String and then use it as a buffer to output text to.
If this dll is created mixed-mode, can it still be interfaced/used in the same way by its COM clients, or do they need to be mixed mode aware?
It can be interfaced the same, but if it's entered via an native entry point, it will try to load the CLR into the process, unless one is already loaded. If the calling client had already loaded CLR prior to the call (or the client was itself called from managed code), then you'll get the CLR that is already loaded, which may be different from the CLR that your code requires (e.g. client may have loaded 1.1, and your code needs 2.0).
Will inclusion of the CLR impose substantial overhead when loading this COM object?
It depends on what you define by overhead. Code size? Runtime penalties? Memory footprint?
In any case, loading the CLR means that you get all the GC and JIT machinery. Those aren't cheap. That said, if you need to call managed code ultimately anyways, there's no way around this - you will have to load CLR into some process to do this. The penalties aren't going to differ between COM Interop and mixed-mode C++/CLI assemblies.

I can't say much about the details like e.g. the string issues, since I never actively used this approach.
But you can easily consume any COM interface from any C# code by simply letting a VS wizard create a proxy for you, there is no performance overhead to it except the one that you always have when invoking COM and .NET.
The other direction, you just have to set your C# assemblies' ComVisibleAttribute to true (in VS it's a simple check box in the project properties), and then the compiler will automatically create COM interfaces for you. Again, there's no additional performance penalty.
HTH!

Related

Using COM dll in C#

We have COM dll which was written in C++ and has been used by the apps written in vb 6.0. My company plans write the newer versions of apps in .Net platform.
As far as the performance is concerned, when using a COM dll in a C# project, what should I choose from the 3 options listed below
Just adding the dll as a com reference
Writing a wrapper dll with C++/Cli
Generating a wrapper dll using TlbImp.exe
Or are there any other options?
Thanks.
Writing a wrapper in C++/CLI isn't that likely to be faster, the COM interop marshaller in the CLR is heavily optimized. It auto-generates machine code stubs from the interop library that you create when you add a reference to the COM server. A does a lot more work that's pretty invisible and very hard to do yourself, related to exceptions.
It makes sure that failure HRESULTs are properly converted to managed exceptions and that managed exceptions cannot leak into the COM server code. The "make it fast" resolve you'll have when you do this will make you cut corners like this. Now you've got something that's fast but unreliable. Getting a managed exception in unmanaged code is brutally hard to diagnose, all the context is gone.
Options 1 and 3 are the same thing. Both generate the interop library, the IDE simply runs the equivalent of Tlbimp for you.
The usual guidance applies here. Do the simple thing first, the interop library is incredibly simple. Only contemplate doing the really hard thing when you can actually measure perf problems and have a realistic idea what to do about it. I've never once seen anybody decide that a C++/CLI wrapper was necessary.
Option 2 is more performant, but not much, especially considering the DLL itself is in VB6.
Not sure if option 3 works at all.
I would personally use option 1, but just keep the interop somewhere safe so that I just keep reusing the same interop and not creating it everytime I add the reference.
Another option is to use new dynamic features and late binding (using Activator to create the object) but that is definitely less performant of all.
Since the component is using COM, it will be easiest to add it as a reference and let visual studio build the proxies. This will be very strait forward and transparent to the .net code. It will not be quite as performant, but most likely it will suit your needs. I would do this first, since it is so easy, and then see how it performs.
If the component was not a COM component, and just a standard c++ dll, then the other two method would probably be a better choice.
A call to COM is slow because of the marshalling of the data. With slow I mean, compared to a call where you do not cross a Managed or COM boundary.
If you need to do a lot of small calls to your COM component, in a performance critical piece of your application, you could wrap (and combine) them with C++.
If the number of calls is minimal, or when they are not performance critical (but aren't all calls performance critical?) I would simply add a reference to the COM dll.
Summary Go for the refence to the COM dll, and test the performance. Since you migrate from VB6, you will get an enourmous performance boost already (string handling in .Net is sooooo much faster).

What are the situations or pros and cons to use of C++/CLI over C#

I have been keeping up with .NET CLR for awhile now, and my language of choice is C#.
Up until recently, I was unaware that C++/CLI could produce "mixed mode" executables capable of running native and managed code.
Now knowing this, another developer friend of mine were discussing this attribute and trying to determine when and how this ability would be useful.
I take it as a given that native code has the capability to be more efficient and powerful than managed code, at the expense of additional development time.
In the past, I resorted to strictly native C++ code libraries and used Interop to make use of the functionality I wrote into the native library.
I can see the benefit of not requiring an additional library, but I'm curious as to what all the pros/cons of using C++/CLI over soley managed executable created in C#, or such an executable using Interop to call a purely native C++ library?
(Sidenote: Are the terms Interop/PInvoke interchangeable, as I d.on't understand the difference between the terms, simply seen them used the same way.)
With C++/CLI you can create, broadly speaking, three types of objects:
Managed types. These will compile down to essentially the same IL as the equivalent C#. There is no performance opportunity here.
Native types. Compiles down to native code as if you'd used straight C++.
Mixed mode types. These compile down to managed code, but allow you to refer to native types too.
You might think of (3) as being like writing C# code with PInvoke code to accessing the native stuff - except all the PInvoke stuff is generated for you.
There's more to it than that, of course, as well as some caveats - but that should give you an idea of how it's useful.
In other words it's really a glue language. While you can write fully fledged apps in C++/CLI it's more normal to keep the managed and native parts separate and use C++/CLI to bridge the two more cleanly than with PInvoke.
Another common use is to extend and existing, native, C++ code base with .Net library calls.
Just be careful that you partition your code well as it can be quite subtle sometimes in compiling your pure C++ code down to IL transparently!
As to your sidenote: PInvoke is a particular type of Interop. Interop comes in other forms too, such as COM Interop. In fact, more accurately, PInvoke is a set of language features that make Interop with native code easier.
I've used Managed C++ (the .NET 1.1 precursor to C++/CLI) effectively in the past. I find it works best when you have a native C or C++ library you wish to use in managed code. You could go the whole Interop/PInvoke route, which makes for some ugly C# code and frequently has marshalling issues, or you could write a managed C++ wrapper, which is where C++/CLI really shines.
Because C++/CLI is managed code, you can call it from C# (or VB.NET if you lean that way) in the normal way, by adding a reference to the .DLL. No marshalling, no dllimport, nothing goofy like that. Just normal project references. Additionally, you get the benefit of static linked libraries if your native library is so designed, which is a Good Thing (tm).
Phil Nash really hit the big things. Here's one more that I've hit more than once and is the primary reason I've used C++/CLI in the past:
Some applications are extended by checked all DLLs in some location for exported functions with a particular name. In C#, there's no way to declare a native C-style export, but you can in C++/CLI. I create a "wrapper" in C++/CLI that exports the method, handles any translation of C structs to managed objects and passes the call on to an assembly written in C#.
There are certain types that are not available to other languages, such as templates,
const and tracking handle of boxed value types.
templates are specialized at compile-time. generics are specialized at runtime. Although CLR should cache generics specialization for future use (so you get the same List each time you use it), there is still a performance hit each time a generics specialization is requested.
i know other languages discard the const attribute, but have compile time checking in your C++ code is better than nothing.
Having a type like int^ allows you to access the memory on the managed heap directory without unnecessary unboxing. This can help performance when passing tracking handles of boxed values to functions that expect a tracking handle, such as Console::WriteLine(Object^). Of course the early boxing initialization can not be avoided. In other languages you can store the reference in an Object variable and pass it around to avoid unboxing, but you lose the compile time type check.

How to use cross platform C++ with a WPF C# GUI

I'm currently in a project that need to work both on Mac and Windows. We are using standard portable C++ for all the application logic. However, since we want the app to feel totally native on both platform, the GUI will be written with C#/WPF for Windows and Objective-C/Cocoa for Mac.
However, for the windows part, I am wondering what is the best way to use the C++ code with C#. C# is managed, and I know that we can use managed C++ too. However I worry that using C++ inside the CLR may introduce unexpected bugs, or that we will need to put an awful lot of #ifdef WIN32 everywhere in the C++ code to make it work both with the managed CLR and the unmanaged environnement of Mac OS X (note that we sure expect to put some ifdef, but we'd like to keep it under control if possible). So basically, what is the best way to use the C++ code with the C# code? Right now, I'm thinking of three solutions
1- Compile the C++ as C++/CLI and directly use the classes and function from C#.
2- Compile and wrap the C++ in an unmanaged win32 dll and call it from C# using DllImport
3- Wrap the C++ in a COM wrapper and use the .NET COM Interop to link it with C#
Which one is the best way? Or, if there is a better solution, what is it?
C++/CLI has several restrictions over standard C++ that don't always make it easy to recompile standard C++ as C++/CLI. Keep in mind that you'll have to distinguish 'managed' and 'unmanaged' pointers, for starters. As these are using different symbols, you've got your first set of #ifdefs right there. And then you get to ref and value classes and all that sort of fun.
You can however use C++/CLI to bridge the gap between native code and the .NET world. The last time I did something along the lines of what you're planning to do, I used C++/CLI to write the bridging layer that did the necessary translation and conversion work between .NET types and classes and the native world. The C++/CLI layer can obviously be used from any .NET language.
You can't always use (2) - this depends very much on the data types you're trying to exchange between the two worlds. The .NET marshalling code is pretty good at dealing with C PODs but anything more complicated and you've got a problem.
(3) is overkill IMHO and introduces another point of failure, plus you're then doing .NET <-> COM <-> native instead of the simpler .NET <-> native if you created your own bridging code. Not to mention that you add complication to your code that won't benefit the other OS you're targeting, namely OS X.
Our development team has been using C++/CLI compiled code with ASP.NET and WPF front ends for while now.
The first major issue we had was build time. The code base would be 150k lines (40+ projects) and took forever to link (due to linker issues we could not build the individual projects as DLL's). We were only able to resolve this issue by wrapping the code with managed C++ classes and building our projects as assemblies.
The second major issue was performance. We originally compiled with /clr (before pure option existed) and this resulted in double thunking of most of our calls that occurred in the managed C++ layer. We fixed this by switching to /clr:pure. By doing so we ran into an
issue where our assemblies resulted in having too many 'global' methods in the assemblies so they would not load. We had to split our assemblies further to solve this issue.
Best and easier way is to do it with .NET <-> COM because COM has much stronger bridge compared to native dll access inside .NET because it may lead to lots of memory issues and lots of troubleshooting time. Its easier to test COM inside any MFC project and get the trace information for debugging and when the component is ready it can be easily used inside .NET.
CLI will not let you use all features and unfortunately its fairly new so less documentation is available and you will not get good support for your questions.
Win32 dll and DLLImport has problems mainly to troubleshoot, because the exception thrown inside Win32 dll will not travel further along the stack instead it will simply crash and you will not get the reason. Where else in COM you can catch exception internally and the COMException thrown inside .NET will not crash your entire application.
COM will be little slower in performance, but it will be more organized and good design pattern to develop.

C++ calling C# options

We have native Win32 C++ code and a set of C# assemblies which we wish to call from the C++ code. I summaries our optios as:
Use COM. The C# code would need to be decorated with additional attributes (GUID, COMVisible). The C# assemblies would need to be registered regasm and would then be available to the native C++ code via COM.
Use a C++/CLI (formerly managed C++) wrapper class. A C++ class could be added to the native C++ project. That class would be compiled with /clr. The native C++ code would call the C++/CLI class which would then call the .Net code. No COM involved. The CLR is started by magic as required with marshalling handled by the C++/CLI extenstions.
Host an instance of the CLR in the native C++ code.
I'm going to discount option 3 as I don't see the benefits over option 2 other than we lose the need for a wrapper class. So the question is, what are the pros/cons of option 1 versus option 2?
Thanks in advance.
Option 2 will perform the best, and be the most seamless and maintainable, IMO.
There is really no advantage to option 1 that I've found. Using C++/CLI seems to function much better, work faster, and be much simpler in general.
You also can, btw, just use the C# assembly directly without having a wrapper class. This does require compiling any files that want to use it with /CLR, but it works quite well.
For option 1 your main pro would be not having to write a wrapper class which can get hairy depending on your project.
For option 2 you won't have to modify your managed library to facilitate unmanaged use, which is sometimes not an option.
For me it comes down to where you want to make your code changes.
With option 2 you also have a pretty straightforward way of subsequently convert your whole application to C++/CLI to avoid the managed/unmanaged transitions that you will get. The transitions could be an issue depending on how you use your referenced assemblies i.e. getting a performance hit.
So far I have had only positive experiences with C++/CLI and can recommend going that route.

Unmanaged to Managed options: performance considerations

Preliminary: The caller is a native EXE that exposes a type of "plugin" architecture. It is designed to load a DLL (by name, specified as a command line arg). That DLL must be native, and export a specific function signature. The EXE is C++, which isn't too important since the EXE is a black box (cannot be modified/recompiled). The native DLL can meet the application needs by completely implementing the solution natively, in said DLL. However, a requirement is to allow the real work (thus turning the native DLL into a thin wrapper/gateway) to be coded in C#. This leads me to 3 options (if there are more, please share):
Native DLL loads a C++/Cli DLL that internally makes use of a C# class library
Native DLL interacts with a C# COM object via CCW
Native DLL hosts CLR and makes calls to C# assembly
One more requirement is that not only does the native DLL need a way to send messages (call functions) on the C#, but the C# needs to be able to fire events/callback to the native DLL when certain extraordinary things occur (as opposed to shutting down and returning). Now this last thing I'm not sure how to handle in the 3rd option, but that is another question altogether.
So to the point: performance. Any info regarding those approaches (assuming they all meet the requirements)? From my investigation, my understanding is 2 would have more overhead than 1, but I'm not 100% confident, which is why I'm here. As for 3, I just don't have any info yet.
So if anyone has dealt with these (or knows of another elegant option), please chime in.
Thanks!
I've done option 1 before, with reasonable success. I don't remember any significant performance implications, though my application wasn't terribly performance-intensive. It seems to me that if performance problems occur, a likely culprit might be the frequent, small native-to-managed transitions. Would it be possible to batch those at the C++/CLI layer?

Categories

Resources