[Interop] Call into .net/managed code from native/unmanaged code

Introduction

I’ve got a native console application which would like to call into a piece of managed code written in C#. This is the how the C# function “Sum” looks like…

image

My solution explorer looks as follows…

image

CSharpModule is a CSharp library while TestManagedCall is a native/unmanaged project. My requirement is as follows: call Class1.Sum from TestManagedCall project.

 
Adding Reference

To do this we’ll need to first add a reference of CSharpModule to TestManagedCall project. Go to project properties of TestManagedCall project and add a reference to CSharpModule project, see below screenshot…

image

So the reference of CSharpModule is now added to TestManagedCall project.

 
Project changes

Next step is to add a new C++ file to TestManagedCall project. I’ll call the file: CSharpModuleWrapper.cpp, this class will act as a wrapper to our managed library: CSharpModule. This is how my solution will explorer look now…

image

Right click on CSharpModuleWrapper.cpp in the solution explorer, select properties, and enable CLR for just this one file

image

 
Fixing incompatibilities

Click “Ok”. Now do a full rebuild. You should see following errors pop up, fix them one by one since adding CLR support results in these incompatibilities… (you’ll see these errors popup one by one, so fixing one will lead to another. Keep fixing them and you’ll see the next error).

  1. cl : Command line error D8016: ‘/ZI’ and ‘/clr’ command-line options are incompatible. Open the file’s(CSharpModuleWrapper.cpp) properties and go to “All Options” under C/C++ node. This is a cool feature to quickly search for an option the properties dialog. Search for /ZI as given in the above error message. CLR compilation doesn’t support /ZI change it to /Zi.
    image
  2. cl : Command line error D8016: ‘/clr’ and ‘/Gm’ command-line options are incompatible. Again open file’s properties and goto “All Options” under C/C++ node. Search for /Gm as given in the above message… (disable minimal rebuild). Change to /Gm-
    image
  3. cl : Command line error D8016: ‘/clr’ and ‘/EHs’ command-line options are incompatible. In file’s properties search for /EHs. Switch to /EHa.
    image
  4. cl : Command line error D8016: ‘/clr’ and ‘/RTC1’ command-line options are incompatible. Change to Default as shown below…
    image
  5. Disable pre-compiled headers as shown below, search for /Yu under “C/C++->All options”…
    image

With these changes your code will compile. I get following output…

image

 
Code Changes

Now add code to use the CSharpModule’s namespace and add a function to CSharpModuleWrapper class. Eventually this is how my code will look like with all the modifications…

image

The CSharpModuleWrapper.h has only one change, I added a declaration for Call_Sum().

Don’t forget to call Call_Sum(). This is how the calling code looks like…

image

 
Output…

image

This is a reliable way to make calls into managed world from native world. Of course there are #pragma’s (managed/unmanaged) that you can use but I’m not so confident about using them. This is clean!

 
Conclusion

The sample I’ve shown is a ‘very’ simple one, I’m sure you’ll have a variety of requirements, let me know if I can help.

Appreciate your comments...