C sharp - Native Interoperability in C# (P/Invoke & COM Interop)

C# runs on the .NET runtime, which is managed code.
But sometimes you must interact with unmanaged code such as:

  • Windows API (Win32)

  • C/C++ DLLs

  • Legacy COM components

  • Hardware drivers

This interaction is called Interoperability (Interop).

There are two main mechanisms:

  1. P/Invoke (Platform Invocation)

  2. COM Interop


Part 1: P/Invoke (Platform Invocation)

What is P/Invoke?

P/Invoke allows C# to call functions inside native DLLs.

It is used when:

  • You need low-level OS functionality

  • You want to use existing C/C++ libraries

  • You need performance-critical native code


1. Basic Example (Calling Windows API)

using System;
using System.Runtime.InteropServices;

class Program
{
    [DllImport("user32.dll")]
    public static extern int MessageBox(IntPtr hWnd,
                                        string text,
                                        string caption,
                                        uint type);

    static void Main()
    {
        MessageBox(IntPtr.Zero, "Hello", "Title", 0);
    }
}

Explanation:

  • DllImport tells C# which DLL contains the function.

  • extern means implementation is outside .NET.

  • The function executes inside unmanaged Windows code.


2. Important Concepts in P/Invoke

1. Marshaling

Managed and unmanaged memory formats differ.

Marshaling converts:

  • C# types → Native types

  • Native types → C# types

Example:

  • C# string → C-style char*

You can control marshaling:

[DllImport("SomeNative.dll")]
public static extern void Function(
    [MarshalAs(UnmanagedType.LPStr)] string text);

2. Struct Layout

When passing structs:

[StructLayout(LayoutKind.Sequential)]
public struct MyStruct
{
    public int A;
    public double B;
}

Without correct layout:

  • Memory mismatch occurs

  • Application may crash


3. Calling Convention

Native functions use different calling conventions:

[DllImport("SomeDll.dll",
    CallingConvention = CallingConvention.Cdecl)]

Wrong convention → stack corruption.


3. When to Use P/Invoke

  • Access Windows system APIs

  • Interact with device drivers

  • Use performance-critical C libraries

  • Interact with legacy native systems


Part 2: COM Interop

What is COM?

COM = Component Object Model
It is an older Microsoft technology for software components.

Used heavily in:

  • Microsoft Office automation

  • Legacy enterprise systems

  • Windows components


1. Example: Using Excel from C#

using Excel = Microsoft.Office.Interop.Excel;

class Program
{
    static void Main()
    {
        var excelApp = new Excel.Application();
        excelApp.Visible = true;
        var workbook = excelApp.Workbooks.Add();
    }
}

Here:

  • C# interacts with Excel COM object.

  • Excel is unmanaged code.


2. Runtime Callable Wrapper (RCW)

When C# uses a COM object:

  • .NET creates an RCW

  • RCW converts managed calls to COM calls

  • Handles reference counting


3. COM Object Cleanup

Unlike .NET garbage collection, COM uses reference counting.

So you must release manually:

Marshal.ReleaseComObject(excelApp);

Otherwise:

  • Memory leaks occur

  • Excel may remain in background


Managed vs Unmanaged Memory

Managed (.NET) Unmanaged
Garbage collected Manual memory management
Type-safe Less safe
CLR controlled OS controlled

Interop bridges these two worlds.


Risks of Interop

  1. Memory leaks

  2. Crashes

  3. Security vulnerabilities

  4. Performance overhead

  5. Platform dependency

Interop should be used only when necessary.


Performance Consideration

Calling unmanaged code has overhead:

  • Marshaling cost

  • Context switching

  • Boundary crossing

Avoid frequent small calls.
Prefer batching operations.


Real-World Use Cases

  • Game engines using C++ physics libraries

  • Image processing libraries

  • Financial trading systems

  • Hardware communication