Cargando...

Interop en C# (Uso de bibliotecas C/C++)

Aprende Interop en C# para trabajar con bibliotecas C/C++, incluyendo P/Invoke y código no administrado.

En las aplicaciones .NET, a veces es necesario aprovechar bibliotecas existentes en C o C++. A esta situación se le llama Interop (interoperabilidad). El lenguaje C# permite acceder a código no administrado mediante el atributo DllImport. De este modo, se pueden llamar directamente a funciones de alto rendimiento o de nivel del sistema.


Llamar a una función nativa con DllImport

En Windows, es posible llamar directamente desde C# a funciones de bibliotecas del sistema como user32.dll o kernel32.dll. Para ello, se utiliza el espacio de nombres System.Runtime.InteropServices.


using System;
using System.Runtime.InteropServices;

class Program
{
    // Importamos una función de la API Win32
    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    public static extern int MessageBox(IntPtr hWnd, string text, string caption, int type);

    static void Main()
    {
        MessageBox(IntPtr.Zero, "¡Hola Interop!", "Ejemplo Interop", 0);
    }
}

Aquí se llama a la función API Win32 MessageBox. Aunque se compile en C#, en realidad se está ejecutando código nativo (C).


Llamar a una función escrita en C

También puedes utilizar una biblioteca C/C++ que hayas escrito tú mismo (por ejemplo mylib.dll). Primero, se define una función en el lado de C:


// mylib.c
__declspec(dllexport) int AddNumbers(int a, int b)
{
    return a + b;
}

// Importación en C#
using System.Runtime.InteropServices;

class NativeMethods
{
    [DllImport("mylib.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern int AddNumbers(int x, int y);
}

class Program
{
    static void Main()
    {
        int resultado = NativeMethods.AddNumbers(5, 7);
        Console.WriteLine($"Suma: {resultado}");
    }
}

En este ejemplo, la función AddNumbers escrita en C se llama desde C#. Los parámetros se convierten automáticamente al tipo adecuado gracias al marshaling.


Struct y Marshaling

En las bibliotecas C no solo se usan tipos simples, sino también struct. En este caso, la misma estructura debe definirse en el lado de C# con el atributo StructLayout.


// Lado C
typedef struct
{
    int width;
    int height;
} Size;

__declspec(dllexport) int CalcArea(Size s)
{
    return s.width * s.height;
}

// Lado C#
[StructLayout(LayoutKind.Sequential)]
public struct Size
{
    public int width;
    public int height;
}

class NativeMethods
{
    [DllImport("mylib.dll")]
    public static extern int CalcArea(Size s);
}

class Program
{
    static void Main()
    {
        var tamano = new Size { width = 10, height = 20 };
        int area = NativeMethods.CalcArea(tamano);
        Console.WriteLine($"Área: {area}");
    }
}

Rendimiento y Seguridad


TL;DR

  • Interop: Permite acceder a bibliotecas C/C++ desde C#.
  • Las funciones nativas se llaman con el atributo DllImport.
  • Los structs se deben mapear correctamente con StructLayout.
  • Tiene un costo de rendimiento; se debe usar con precaución.

Artículos relacionados