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:



  1. Create a WinForms C++ project in VS 2005.
  2. 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:

  3. 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.
  4. Open the project properties and add the netmodule that is created from the C# class as input to the C++ linker:

  5. Now add a “#using” directive to the Form.h:

  6. And that’s it: you can now reference the C# class in the C++ editor, even IntelliSense is working:

  7. 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.


—-


Addendum, 2004-09-08:


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!

Comments (13)

  1. Sam says:

    now THIS is cool. Can you mix all languages together (eg VB.NET and C#?)

  2. I have to wonder how this "feature" affects code maintainability. Instead of being able to say that to develop for X library, you need to know C++ or C#, you now have a scenario where it’s not unfeasible that a given developer assigned bugfixing tasks will need to know C++, C#, VB.Net and any other languages which have been used in the assembly.

    I mean, it’s cool and all, but I can see it causing more problems than it solves – and I can’t really see it solving any problems to be honest.

  3. FrankPr says:

    Sam:

    It looks like at the moment only in C++ projects you can add other languages’ source files (whichever you want – as long as there is a command-line compiler which can be used in a custom build step :-). Maybe you could create an *empty* C++ project and add C# and VB.NET to it…

    Simon:

    Sure, this goes against the concept of componentization, but OTOH it can save you from deployment hassles in certain scenarios. (I’m sure *someone* will find this useful.) Note that, as an alternative, you could create netmodules in "ordinary" C# or VB project, and only add that output as a linker input to the C++ project. That way, you could maintain the sources separately, and only have the outputs linked together in the build process. Does it make sense? Well, does static linking make sense, anyway? That’s a matter of taste, I suppose… 😉

  4. Sam says:

    Simon: You definetly wouldn’t use this for everything, but maybe you’re working on a VB.NET project with a custom low level communication protocol. Previously you’d have to have a c++ dll and call it from vb.net, now you can compile it all togeather (if you want)…

  5. Peter Huene says:

    Also, take a look at custom build rules (a new feature in 2005) which I cover in my blog (my url). In theory, someone could author a custom build rule for .cs files so you don’t have to configure a custom build step for every .cs file in the project (you can even build multiple .cs files into the same output using a target custom build rule). With the property page customization, you could create friendly properties for corresponding switches on csc.

  6. FrankPr says:

    Peter:

    This makes a cool story even greater! Thanks for providing this information.

    Do you have some "generic" build rules for common things like C# or VB files that you could share?

  7. You can do Multilanguage assemblies already with the .NET 1.x Version (/t:module switch for C# or VB) from the commandline and you can tweak VS2003 using build rules to integrate this into a solution.

    The resulting assembly will be a multifile assembly consisting of several netmodules.

    I understand why people are exited about integrationg that all into a singlefile assemby, but I also strongly recommend to educate people more about the advantages of multifile assemblies if it comes to assemblies that should be loaded over the network. .NET is smart enough to load on demand only the netmodule that contains the code to be jitted, so netmodules are an elegant way to make downloads more granular for large assemblies.

  8. Sam says:

    have you actually TRIED to have a multilanguage assembly before? Its a pain in the arse. I understood vs.net 2005 was moving this to the IDE.

  9. When you refer to C++ here, I guess you mean "Managed C++".

  10. FrankPr says:

    Murray:

    Yes, of course. "IL linking" and "assembly" imply this, I guess. But you’re right, should have said that explicitly.