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
- Las llamadas Interop son más lentas que los métodos normales de C# (costo de marshaling).
- Los errores en el código no administrado (fugas de memoria, errores de puntero) pueden bloquear directamente la aplicación.
- Por lo tanto, solo debe usarse cuando sea realmente necesario.
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
Conversiones de tipos en C#
Aprende las conversiones de tipos en C#, incluyendo casting implícito y explícito, Parse, TryParse y métodos Convert con ejemplos.
Manejo de excepciones en C# (try, catch, finally)
Aprende a manejar excepciones en C# usando bloques try, catch y finally para gestionar errores de forma segura con ejemplos.
Structs en C# – Diferencias con las clases
Aprende las diferencias entre structs y clases en C#, incluyendo modelo de memoria, herencia y rendimiento.
Tipos de datos básicos en C#
Tipos de datos básicos en C#: numéricos, de texto, lógicos, orientados a objetos y anulables.