.NET Interoperability at a Glance 2 – Managed Code Interoperation


This article is available also in blog here.

Overview

In the previous article, you learned what interoperability is and how it relates to the .NET Framework. In this article, we're going to talk about the first form of interoperability, the Managed Code Interop. In the next article, we'll talk about other forms.

Introduction

So, to understand Interoperation well in the .NET Framework, you must see it in action. In this article, we'll talk about the first form of .NET interoperability and see how to implement it using the available tools.

Just a reminder, Interoperability is the process of communication between two separate systems. In .NET Interop, the first system is always the .NET Framework; the other system might be any other technology.

Forms of Interop

Interoperability in .NET Framework has two forms:

  • Managed Code Interoperability
  • Unmanaged Code Interoperability
Next, we have a short discussion of each of the forms.

Managed Code Interop

This was one of the main goals of .NET Framework. Managed Code Interoperability means that you can easily communicate with any other .NET assembly no matter what language used to build that assembly.
  • Not surprisingly, because of the nature of .NET Framework and its runtime engine (the CLR,) .NET code supposed to be called Managed Code, while any other code is unmanaged.

To see this in action, let's try this:
  1. Create a new Console application in the language you like (C#/VB.NET.)
     
  2. Add a new Class Library project to the solution and choose another language other than the one used in the first project.
     
  3. In the Class Library project, add the following code (choose the suitable project):

    // C#
    public static class Hello
    {
        public static string SayHello(string name)
        {
            return "Hello, " + name;
        }
    }

    ' VB.NET
    Public Module Hello
       
     
    Public Function SayHello(ByVal name As String) As String
            Return "Hello, " & name
       
     
    End Function
    End
     Module
     

  4. Now, go back to the Console application. Our goal is to call the function we have added to the other project. To do this, you must first add a reference to the library in the first project. Right-click the Console project in Solution Explorer and choose Add Reference to open the Add Reference dialog (figure 1.) Go to the Projects tab and select the class library project to add it.

    image1.gif
     
  5. Now you can add the following code to the Console application to call the SayHello() function of the class library.

    // C#
    static void Main()
    {
        Console.WriteLine(ClassLibrary1.Hello.SayHello(
    "Mohammad Elsheimy"));
    }
    ' VB.NET
    Sub Main()
        Console.WriteLine(ClassLibrary1.Hello.SayHello("Mohammad Elsheimy"))
    End Sub
How did this happen? How could we use the VB.NET module in C# which is not available there (or the C#'s static class in VB which is not available there too)?

Not just that, but you can inherit C# classes from VB.NET (and vice versa) and do all you like as if both were created using the same language. The secret behind this is the Common Intermediate Language (CIL.)

When you compile your project, the compiler actually doesn't convert your C#/VB.NET code to instructions in the Machine language. Rather, it converts your code to another language of the .NET Framework, which is the Common Intermediate Language. The Common Intermediate Language, or simply CIL, is the main language of .NET Framework which inherits all the functionalities of the framework, and which all other .NET languages when compiled are converted to it.

So, the CIL fits as a middle layer between your .NET language and the machine language. When you compile your project, the compiler converts your code to CIL statements and emits them in assembly file. In runtime, the compiler reads the CIL from the assembly and converts them to machine-readable statements.

How CIL helps in interoperation? The communication between .NET assemblies is now done through the CIL of the assemblies. Therefore, you don't need to be aware of structures and statements that are not available in your language since every statement for any .NET language has a counterpart in IL. For example, both the C# static class and VB.NET module convert to CIL static abstract class (see figure 2.)

image2.gif

Managed Interop is not restricted to C# and VB.NET only; it's about all languages run inside the CLR (i.e. based on .NET Framework.)

If we have a sneak look at the CIL generated from the Hello class which is nearly the same from both VB.NET and C#, we would see the following code:
    .class public abstract auto ansi sealed beforefieldinit ClassLibrary1.Hello extends [mscorlib]System.Object
{
    .method public hidebysig static string SayHello(string name) cil managed
{
    // Code size 12 (0xc) .maxstack 8 IL_0000: ldstr "Hello, " IL_0005: ldarg.0 IL_0006: call string [mscorlib]System.String::Concat(string, string) IL_000b: ret
} // end of method Hello::SayHello }
   
// end of class ClassLibrary1.Hello

On the other hand, this is the code generated from the Main function (which is also the same from VB.NET/C#):

 .class public abstract auto ansi sealed beforefieldinit
    ConsoleApplication1.Program extends [mscorlib]System.Object
{
    .method private hidebysig static void Main() cil managed
{
    .entrypoint .maxstack 8 IL_0000: ldstr "Mohammad Elsheimy" IL_0005: call string [ClassLibrary1]ClassLibrary1.Hello::SayHello(string) IL_000a: call
    void [mscorlib]System.Console::WriteLine(string) IL_000f: ret }
// end of method Program::Main }
// end of class ConsoleApplication1.Program

 
You can use the ILDasm.exe tool to get the CIL code of an assembly. This tool is located in Program Files\Microsoft SDKs\Windows\<version>\bin.

Here comes a question, is there CIL developers? Could we write the CIL directly and build it into .NET assembly? Why we can't find much (if not any) CIL developers? You can extract the answer from the CIL code itself. As you see, CIL is not so friendly and its statements are not so clear. Plus, if we could use common languages to generate the CIL, we we'd like to program in CIL directly? So it's better to leave the CIL for the compiler.

Now, let's see the other form of .NET interoperation, Unmanaged Code Interoperability.

Summary

So, the secret of Managed Code Interoperation falls in the Common Intermediate Language or CIL. When you compile your code, the compiler converts your C#/VB.NET (or any other .NET language) to CIL instructions and saves them in the assembly, and that's the secret. The linking between .NET assemblies of different languages relies on the fact that the linking is actually done between CILs of the assemblies. The assembly code doesn't (usually) have any clue about the language used to develop it. In the runtime, the compiler reads those instructions and converts them to machine instructions and execute them.

Next, we'll talk about the other form of .NET Interoperation, it's the interoperation with unmanaged code.


Similar Articles