Interop en C# (Utilisation de bibliothèques C/C++)
Apprenez l’Interop en C# pour utiliser des bibliothèques C/C++, y compris P/Invoke et la gestion du code non managé.
Dans les applications .NET, il est parfois nécessaire d’utiliser des bibliothèques C ou C++ existantes.
Cette situation est appelée Interop (interopérabilité).
Le langage C# permet d’accéder au code non managé grâce à l’attribut DllImport.
Ainsi, des fonctions hautes performances ou de bas niveau système peuvent être appelées directement.
Appeler une fonction native avec DllImport
Sous Windows, il est possible d’appeler directement depuis C# des fonctions provenant de bibliothèques système
telles que user32.dll ou kernel32.dll.
Pour cela, on utilise l’espace de noms System.Runtime.InteropServices.
using System;
using System.Runtime.InteropServices;
class Program
{
// Import d’une fonction de l’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, "Bonjour Interop !", "Exemple Interop", 0);
}
}
Ici, la fonction API Win32 MessageBox est appelée.
Bien que compilé en C#, c’est en réalité du code natif (C) qui s’exécute.
Appeler une fonction écrite en C
Vous pouvez également utiliser une bibliothèque C/C++ que vous avez écrite vous-même (par exemple mylib.dll).
Tout d’abord, définissez une fonction côté C :
// mylib.c
__declspec(dllexport) int AddNumbers(int a, int b)
{
return a + b;
}
// Import côté 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 resultat = NativeMethods.AddNumbers(5, 7);
Console.WriteLine($"Somme : {resultat}");
}
}
Dans cet exemple, la fonction AddNumbers écrite en C est appelée depuis C#.
Les paramètres sont automatiquement convertis vers le type approprié grâce au marshaling.
Struct et Marshaling
Les bibliothèques C n’utilisent pas seulement des types simples, mais aussi des struct.
Dans ce cas, la même structure doit être définie côté C# avec l’attribut StructLayout.
// C côté
typedef struct
{
int width;
int height;
} Size;
__declspec(dllexport) int CalcArea(Size s)
{
return s.width * s.height;
}
// C# côté
[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 taille = new Size { width = 10, height = 20 };
int surface = NativeMethods.CalcArea(taille);
Console.WriteLine($"Surface : {surface}");
}
}
Performance et Sécurité
- Les appels Interop sont plus lents que les méthodes C# normales (coût du marshaling).
- Les erreurs dans le code non managé (fuites mémoire, erreurs de pointeur) peuvent planter directement l’application.
- Par conséquent, il ne doit être utilisé que lorsque c’est réellement nécessaire.
TL;DR
- Interop : Permet d’accéder aux bibliothèques C/C++ depuis C#.
- Les fonctions natives sont appelées avec l’attribut
DllImport. - Les structs doivent être correctement mappés avec
StructLayout. - Il existe un coût en performance ; à utiliser avec précaution.
Articles connexes
Conversions de types en C#
Apprenez les conversions de types en C#, y compris le casting implicite et explicite, Parse, TryParse et Convert avec exemples.
Gestion des exceptions en C# (try, catch, finally)
Apprenez à gérer les exceptions en C# avec les blocs try, catch et finally afin de traiter les erreurs de manière sûre avec exemples.
Structs en C# – Différences avec les classes
Découvrez les différences entre structs et classes en C#, notamment le modèle mémoire, l’héritage et les performances.
Types de données de base en C#
Types de données de base en C# : numériques, textuels, logiques, orientés objet et nullables.