Mix languages in C++ projects in VS 2005
Some time ago I wrote about a new feature that's coming in VS 2005: projects that contain source files in different languages (C++, C#, VB.NET, ...), which are combined into a single assembly. (That is really new & exciting because today you can only combine different language projects in a common solution - which still gives separate assemblies from each project which have to be linked together dynamically).
Well, recently I looked into this again after Beta 1 became available, and I have to qualify my earlier statement a little bit, although the main message still stands and continues to excite me :-)
So what's up with this? The fact is: thanks to custom build steps, MSIL linking (the ability to statically link netmodules into one assembly), and other cool features of the new C++ compiler in Whidbey, you can add C# and VB.NET (and other) source files to a .NET C++ project, and build everything together into a single EXE or DLL. Cool, eh?
OK, so if this is old hat to you, go somewhere else, otherwise read on, if you want to find out how it works. I've made a quick & dirty sample (nothing polished, just POC), which I'll describe below:
- Create a WinForms C++ project in VS 2005.
- Create a C# class file using the editor of your choice (you can't directly add one to a C++ project...), and copy that into the project directory (windows explorer ...), then include it into the project (IDE). Looks like this:
- Then right-click on the class file in solution explorer, select "Properties", and create a custom build step for this file:
(Obviously we have to bring the C# compiler in here somehow - during build, the C++ won't know what to do with a C# source file... :-). We create a netmodule here, so this can be IL linked into the final EXE.
- Open the project properties and add the netmodule that is created from the C# class as input to the C++ linker:
- Now add a "#using" directive to the Form.h:
- And that's it: you can now reference the C# class in the C++ editor, even IntelliSense is working:
- Build the project, and run it.
The cool thing is that you have no dependency on the netmodule - it has been compiled into the EXE, which is all you would have to deploy.
You can download my sample here.
After the Comments section has been closed, I received the following example where the above would be useful, from Tom Trias of Afni Insurance Services, and I post it here with his permission:
"Just thought I'd share an instance where I needed to use this:
I have a Web Service, written in VB.NET, using WSE 2.0. It's in VB.NET, because the rest of our developers are primarily comfortable in VB and we've been transitioning to .NET, so it seemed like the easiest migration.
Unfortunately, the Web Service proxy will still be called by legacy code in ASP (VBScript) and VB 6. So, we have setup COM interop interfaces on the proxy. I ran into an issue with Currency Properties in an Interface and the resolution of the MarshalAs attribute: it marked the get, but not the set as Currency. Mattias Sjorgen confimred that I couldn't solve the issue in VB.NET.
So, now we have interface definitions in C#, class implementations in VB.NET, and I have to deploy 2 (or 3 depending upon whether I go the assembly manifest route) files instead of compiling it all into one DLL.
I think I would create an empty managed C++ project just to be able to ship one file, since it IS the replacement for a single COM DLL.
Of course, it might be nice if the VB and C# compilers could optionally spit out the MSIL; I know I can disassemble and then reassemble, but there is no guarantee that the same optimizations will be performed...
Anyway, that's my 2 cents."
Thanks, Tom, for sharing this thought!