CodeBlanks Logo Icon CodeBlanks

Summary - P/Invoke and interop

C# course · Expert · Lesson 18/47

Combine DllImport, Marshal and StructLayout to write a native wrapper.

Summary - P/Invoke and interop

In this group you learned DllImport, Marshal, StructLayout, string marshalling and delegate*. These are the ways to call native code (C libraries, Win32 API) from C#.

Choosing the right marshal type and managing memory by hand is critical for interop safety. Let's now write a small native wrapper.

Exercise Point struct and Marshal.SizeOf

Add the [StructLayout(LayoutKind.Sequential)] struct Point { public int X; public int Y; } struct. In Main write Point p; p.X = 10; p.Y = 20;, get the size with int size = Marshal.SizeOf<Point>(); and print it with Console.WriteLine(size);.

Show example solution
Point p; p.X = 10; p.Y = 20; int size = Marshal.SizeOf<Point>(); Console.WriteLine(size);
Example solution:
using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential)]
struct Point
{
    public int X;
    public int Y;
}

class Program
{
    static void Main()
    {
        Point p;
        p.X = 10;
        p.Y = 20;
        int size = Marshal.SizeOf<Point>();
        Console.WriteLine(size);
    }
}

Memory and lifecycle

In interop code the key rule: always release memory you allocated with Marshal (FreeHGlobal). Strings that DllImport marshals automatically do not need this, but manual Marshal calls can leak.

Guaranteeing release with a using statement or try/finally is the best practice. This ensures the resource is reclaimed even on error paths.

Exercise Call abs via DllImport

Add the declaration [DllImport("libc.so.6")] static extern int abs(int n);. In Main compute the absolute value with int r = abs(-7); and print it with Console.WriteLine(r);.

Show example solution
int r = abs(-7); Console.WriteLine(r);
Example solution:
using System;
using System.Runtime.InteropServices;

class Program
{
    [DllImport("libc.so.6")]
    static extern int abs(int n);

    static void Main()
    {
        int r = abs(-7);
        Console.WriteLine(r);
    }
}

Test yourself

  1. Which copies a managed string to native memory?

    • Marshal.StringToHGlobalAnsi
    • GC.Collect
    • Thread.Sleep
    • Console.WriteLine
    Show answer

    Marshal.StringToHGlobalAnsi — Correct. Marshal.StringToHGlobalAnsi puts a string in native memory.

  2. Match the concepts

    DllImport
    Native method call
    Marshal
    Manual conversion
    StructLayout
    Memory layout
    delegate*
    Function pointer

All lessons in Expert