Click here to Skip to main content
13,804,051 members
Click here to Skip to main content
Add your own
alternative version


61 bookmarked
Posted 4 Apr 2005

Using managed code in an unmanaged application

, 4 Apr 2005
Rate this:
Please Sign up or sign in to vote.
How to use your managed class libraries in your unmanaged application, using IJW.

Please keep in mind that the code of this article is for the .NET Framework 2.0 Beta 1 (C++/CLI). To make this sample work under .NET 1.1, basically use * instead of ^ for the managed types.


When we talk about the .NET platform, people often complain about the same things:

  • Speed
  • Garbage collection
  • No backward compatibility with C or C++

While the first two topics are very well discussed, today I will talk about a relatively unknown feature of the .NET platform: IJW.

What is IJW?

First, IJW stands for "It Just Works", and, at the very first level, it enables you to compile existing C/C++ projects in MSIL, and "It Just Works" ;). To use it, simply add the /clr compiler option, or set the "Common Language Runtime support" option of your project to "Common Language Runtime Support (/clr)". It's as simple as that.

Of course, why recompile an entire C++ project into MSIL when it's working already? Well, the force of IJW is more in the managed/unmanaged interoperability. Let's take a look at what it can offer you with a simple case: mine.

A sample problem

At work, we heavily use remoting to abstract the network transportation layer, and we were very happy with it. Then one problem came: we use some software to handle our sensors and processing dataflow. This software basically allows you to make "components" that you load in it, and then use them. The problem is, the format for a component is very specific and has to be made in C++ (using the provided source generator). So, to overcome this problem, I designed a simple .NET 2.0 library (using generics) and component that use global shared memory and Win32 events to allow IPC between the software process and the .NET process. While this technique works very well, the drawbacks were huge because you couldn't use the remoting functions you needed when you wanted to and were forced to adopt a certain communication convention. Really, it was a pain sometimes, especially when dealing with pointers. Then I came to see IJW.

What IJW can do

Well, with IJW, you can make an executable image (.exe or .dll) with both unmanaged and managed code inside, and allows interoperability between them. For instance, you make an IJW DLL with managed code, and export an unmanaged class or function that uses the managed code. When you will load this DLL in your unmanaged process (via <CODE lang=mc++>__declspec(dllimport) or LoadLibrary()), the CLR will load the managed image inside and will allow you to use the managed code from your unmanaged process. So, to use your managed code from the unmanaged process, you just have to make the proper wrapper. But then one problem comes: you can't have managed type members in an unmanaged class.

And then I already see some of you saying: "Okay great, but how can I make a wrapper around a managed type if I can't store the managed instance in my wrapper? After all, unmanaged classes are not aware of the .NET Platform". And you would be right. However (I bet you suspected), there is a workaround for this.

Storing managed type members in an unmanaged class

.NET provides a way to overcome this via the System.Runtime.InteropServices.GCHandle class. We won't go into GCHandle deeply because, fortunately for us, Microsoft has designed a templated class that wraps GCHandle: gcroot<T>, declared in vcclr.h. So, to use a managed type in an unmanaged class, just declare it as the typed gcroot<T> template. You can then access all its members using the -> symbol.

Note also that you have to use the <CODE lang=mc++>gcnew keyword to instantiate the managed type into the managed heap, this type will then be marked collectable at the gcroot<T> destructor. Here's a sample:

<PRE lang=mc++>#include <vcclr.h> #using <mscorlib.dll> using namespace System; class Unmanaged { private: gcroot<String ^> _myString; public: Unmanaged() { _myString = gcnew String(); } int GetHashCode() { return (_myString->GetHashCode()); } };

Wrapper instantiation

But then another problem comes: the unmanaged client of the DLL wrapper mustn't see any managed stuff (like gcroot<>). So, we'll have to make an interface to the wrapper, and a class factory for it. Let's make a class that wraps a managed class System.Windows.Forms.MessageBox.

First, let's make a managed class called MessageBoxShower in C#:

// MessageBoxShower.cs: a managed class that shows a message box.

using System;
using System.Collections.Generic;
using System.Text;

namespace ManagedClasses
    public class MessageBoxShower
        private string _message = "";

        public MessageBoxShower(string message)
            _message = message;

        public void Show()

Then, let's make the interface to the C++ wrapper: IMessageBoxWrapper. Of course, we don't forget to add a reference to the DLL containing MessageBoxShower.

<PRE lang=mc++>// IMessageBoxWrapper.h: interface to hide // the managed implementation from the dll client #pragma once #include <string> #ifdef MANAGEDWRAPPER_EXPORTS #define DLLAPI __declspec(dllexport) #else #define DLLAPI __declspec(dllimport) #pragma comment (lib, "ManagedWrapper.lib") // if importing, link also #endif class DLLAPI IMessageBoxWrapper { public: virtual void Show(std::string message) = 0; // Class factory static IMessageBoxWrapper *CreateInstance(); static void Destroy(IMessageBoxWrapper *instance); };

After that, we have to make the MessageBoxWrapper class itself:

<PRE lang=mc++>// MessageBoxWrapper.h: actually wrapper to the managed class #pragma once #include <vcclr.h> #include <string> #include "IMessageBoxWrapper.h" using namespace ManagedClasses; class DLLAPI MessageBoxWrapper : IMessageBoxWrapper { private: gcroot<MessageBoxShower ^> _managedObject; public: MessageBoxWrapper() { } void Show(std::string message); };

And finally, implement the class factory code, and the MessageBoxWrapper class:

<PRE lang=mc++>// MessageBoxWrapper.cpp: implementation of MessageBoxWrapper and class factory #include "IMessageBoxWrapper.h" #include "MessageBoxWrapper.h" void MessageBoxWrapper::Show(std::string message) { _managedObject = gcnew MessageBoxShower(gcnew System::String(message.c_str())); _managedObject->Show(); } IMessageBoxWrapper *IMessageBoxWrapper::CreateInstance() { return ((IMessageBoxWrapper *)new MessageBoxWrapper()); } void IMessageBoxWrapper::Destroy(IMessageBoxWrapper *instance) { delete instance; }

And here we are! We can now use our managed class directly in our unmanaged code without the need of any assembly referencing or .NET stuff! Here's a sample file, remember linking is done via <CODE lang=mc++>__declspec(dllimport) in IMessageBoxWrapper.h:

<PRE lang=mc++>// main.cpp: a totaly unmanaged application #include "IMessageBoxWrapper.h" int main(int argc, char **argv) { IMessageBoxWrapper *wrapper = IMessageBoxWrapper::CreateInstance(); wrapper->Show("hey!"); IMessageBoxWrapper::Destroy(wrapper); return (0); }

Data conversion

Data conversion between managed world and unmanaged world is your job; this means you'll have to make a wrapper for each managed type you use between the two worlds. And that's a big drawback of IJW since this can't be automated, because obviously, it depends on your code. However, it can be done anywhere you want. Also, I suggest you to take a look at the System.Runtime.InteropServices.Marshal class, it can be really useful.

Talking about collections, the conversion is also up to you: for instance ArrayList or List<> to std::vector<> or Hashtable to std::map<>, and back.


With this article, we demonstrated that managed code can interoperate very well with unmanaged code, in both directions. And well, I hope, for once, it will help you decide to switch to managed code.

Oh, and don't forget, a common mistake is to forget to put the .NET references needed by your wrapper DLL in the same directory as the executable (not the project!).


03/30/2005 - Initial release.


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Steeve Morin
Web Developer
France France
Born in 1984. Got a computer at 12. Started programming at 14 with VB6.
Actually in third year at the Epitech school in Paris, France.
And part time working at the IMARA project at INRIA.

You may also be interested in...


Comments and Discussions

GeneralMy vote of 5 Pin
MooseWall21-Oct-14 8:46
memberMooseWall21-Oct-14 8:46 
GeneralThank you. Pin
AlecGT16-Dec-13 9:11
memberAlecGT16-Dec-13 9:11 
Questionneed help Pin
Member 96689553-Jul-13 8:19
memberMember 96689553-Jul-13 8:19 
AnswerRe: need help Pin
SeattleHeather10-Jul-13 16:27
memberSeattleHeather10-Jul-13 16:27 
GeneralRe: need help Pin
Member 96689557-Aug-13 11:41
memberMember 96689557-Aug-13 11:41 
GeneralMy vote of 5 Pin
plaster26-Mar-13 5:38
groupplaster26-Mar-13 5:38 
Answerheap corruption errors Pin
plaster9-Oct-12 3:19
groupplaster9-Oct-12 3:19 
igotmymtv200520-Aug-12 7:41
memberigotmymtv200520-Aug-12 7:41 
GeneralRe: DOES NOT WORK Pin
Richard MacCutchan21-Aug-12 23:46
protectorRichard MacCutchan21-Aug-12 23:46 
GeneralMy vote of 5 Pin
Member 4215073-Dec-10 10:05
memberMember 4215073-Dec-10 10:05 
GeneralTHANK YOU!!! Pin
thenutz7217-Mar-09 13:51
memberthenutz7217-Mar-09 13:51 
God Bless You and Your Big Brain1
Generalgcroot is not necessarily needed in the example Pin
gomoku@sina.com11-Nov-07 17:57
membergomoku@sina.com11-Nov-07 17:57 
QuestionProblem when using a Network drive Pin
akiura18-Apr-07 4:20
memberakiura18-Apr-07 4:20 
AnswerRe: Problem when using a Network drive Pin
haddati7-Aug-07 23:39
memberhaddati7-Aug-07 23:39 
GeneralRe: Problem when using a Network drive Pin
akiura8-Aug-07 21:30
memberakiura8-Aug-07 21:30 
GeneralBuilding an MFC Application in Release Mode Pin
Member 176587710-Feb-07 2:24
memberMember 176587710-Feb-07 2:24 
Generaldeployment Pin
nadeemahmad19-Sep-06 3:07
membernadeemahmad19-Sep-06 3:07 
Generalmodifying the string... Pin
d.rikel23-Jun-06 5:06
memberd.rikel23-Jun-06 5:06 
GeneralManaged code threads Pin
robee07-Mar-06 5:08
memberrobee07-Mar-06 5:08 
GeneralRe: Managed code threads Pin
Steeve Morin7-Mar-06 22:15
memberSteeve Morin7-Mar-06 22:15 
Generalgcnew Pin
imsodul24-Aug-05 5:26
memberimsodul24-Aug-05 5:26 
Generalsuggestions Pin
scott_mccaskill2-May-05 12:36
memberscott_mccaskill2-May-05 12:36 
GeneralRe: suggestions Pin
Steeve Morin2-May-05 13:44
memberSteeve Morin2-May-05 13:44 
GeneralRe: suggestions Pin
scott_mccaskill3-May-05 5:03
memberscott_mccaskill3-May-05 5:03 
GeneralCheck out this artical on MSDN Pin
Peter Tewkesbury5-Apr-05 0:29
professionalPeter Tewkesbury5-Apr-05 0:29 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web05 | 2.8.181218.1 | Last Updated 5 Apr 2005
Article Copyright 2005 by Steeve Morin
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid