Click here to Skip to main content
Click here to Skip to main content

Moving Data between Managed Code and Unmanaged Code – Alternative Using C++ and IJW

, 15 Apr 2009 CPOL
Rate this:
Please Sign up or sign in to vote.
Moving data between Managed Code and Unmanaged Code – Alternative using C++ and IJW

Introduction

The natural choice today for a programming language for writing a new piece of software in the Microsoft environment is C#. For various reasons, some parts of the project may be written in other languages (existing packages, third party, performance, etc.). In this short article, I'll suggest what seems to me like a good, easy to manage, alternative for interoperation between managed and unmanaged code.

The .NET Environment

Microsoft got jealous of Java and created its own virtual machine, the CLR. Compilation of code in C# generates a machine code suitable for this virtual machine. Microsoft went one step further so that the code of other languages, such as C++, compiles to the same machine language. It is possible therefore to call from a DLL or an executable in C# to a DLL in C++, and vise versa. Each team uses its preferred programming language and it all fits together in the linkage.

Managed Code vs. Unmanaged Code

Code that runs in the .NET environment is called a managed code. Code that runs as in old days is called unmanaged code. The "management" brings a lot of advantages such as "garbage collection" of memory that was allocated but will never be used again. The disadvantages of the "management" are lesser performance, and the difficulty to interact with existing libraries in unmanaged code.

IJW

Microsoft brings a friendly solution which exists to the best of my knowledge only for C++. The solution enables calling from managed code to unmanaged code and vise versa, It Just Works! The only limitation is that there will be no use of "managed" data types in the unmanaged code. Hence it is possible to pass basic data types such as int, double, and data types that were defined as "not managed". In order to use that feature, we'll create the new DLL, or executable, as a C++ project for CLR (managed), and then we'll surround unmanaged code with:

#pragma unmanaged

#pragma managed

Use Case Example and a Code Snippet

In a project, I defined some classes in C# and created a DLL to hold those. The classes were intended to present a configuration for a real-time program. We decided that the real-time loops and logic will be written in unmanaged C++ code. I've created another DLL which was written in C++ and was also using the CLR. That way the DLL written in C++ could reference the DLL written in C# and use the classes representing the configuration. The program itself wrapping everything was written in C#. Hence the program is familiar with the classes in the C# DLL. It passes them to the C++ DLL, which is also familiar with those classes. There is still one problem left. We need to translate "managed" data types to "unmanaged" data types, in order to call unmanaged code. The work involved here is either trivial or Sisyphean, yet it will be a no-brainer. There is another alternative, which is working with unmanaged data types throughout both the unmanaged and managed code. I suggest that explicit translation is more convenient and self explanatory and is done at the last moment on the border between managed code and unmanaged code.

Following is a code snippet:

*.h File (C++)

public ref class CConfig 
{ 
public: 
    CConfig (int _a, String ^_str, double _d); 
    void doTheStuff (); 
    int m_a; 
    String ^m_str; 
    double m_d; 
};

*.cpp File

#include <stdio.h> 
#include <stdlib.h> 
#include <vcclr.h> 
#include <iostream> 
void someMoreInManaged () 
{ 
    Console::WriteLine("C++ Managed – someMoreInManaged"); 
} 

#pragma unmanaged 
void doTheStuff1 (int _a, double _d, const wchar_t* const _str) { 
    std::cout << "C++ unmanaged – doTheStuff1" << std::endl; 
    std::cout << _a << _std::endl; 
    printf_s("%S\n", _str); 
    std::cout << _d << _std::endl; 
    someMoreInManaged(); 
} 

#pragma managed 
CConfig::CConfig 
(int _a, String ^_str, double _d) { 
    m_a = _a; 
    m_str = _str; 
    m_d = _d; 
} 
void CConfig::doTheStuff () { 
    Console::WriteLine("C++ Managed – doTheStuff"); 
    // Pin memory so GC can't move it while 
    // native function is called – MSDN documentation wchar_t <-> String 
    pin_ptr<const wchar_t> wch = PtrToStringChars(m_str); 
    doTheStuff1 (m_a,m_d,wch); 
}

History

  • 15th April, 2009: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Oren Zeev-Ben-Mordehai

United Kingdom United Kingdom
No Biography provided

Comments and Discussions

 
GeneralMy vote of 2 PinmemberJames Farr2-Oct-09 6:35 
Questionmore info Pinmemberhotbyte6415-Apr-09 13:13 
AnswerRe: more info PinmemberOren Zeev-Ben-Mordehai15-Apr-09 14:31 
GeneralRe: more info Pinmemberhotbyte6415-Apr-09 17:01 
GeneralRe: more info PinmemberAnandChavali18-Apr-09 3:35 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.141223.1 | Last Updated 15 Apr 2009
Article Copyright 2009 by Oren Zeev-Ben-Mordehai
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid