Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Lors du marshaling des données, le marshaleur d’interopérabilité peut copier ou épingler les données à marshaler. La copie des données place une copie de données à partir d’un emplacement de mémoire dans un autre emplacement de mémoire. L’illustration suivante montre les différences entre la copie d’un type valeur et la copie d’un type passé par référence de la mémoire managée à la mémoire non managée.
Les arguments de méthode passés par valeur sont marshalés vers le code non managé en tant que valeurs sur la pile. Le processus de copie est direct. Les arguments passés par référence sont passés comme pointeurs sur la pile. Les types référence sont également passés par valeur et par référence. Comme le montre l'illustration suivante, les types de référence passés en tant que valeurs sont soit copiés, soit fixés en mémoire :
L’épinglage verrouille temporairement les données dans leur emplacement de mémoire actuel, évitant ainsi qu’elles ne soient déplacées par le garbage collector du common language runtime. Le marshaleur épingle des données pour réduire la charge imposée par la copie et pour améliorer les performances. Le type des données détermine si celles-ci sont copiées ou épinglées lors du processus de marshaling. L’épinglage se fait automatiquement pendant le marshaling pour les objets comme String. Cependant, vous pouvez aussi épingler manuellement la mémoire en utilisant la classe GCHandle.
Classes blittables mises en forme
Les classes blittable mises en forme ont une disposition fixe (mise en forme) et une représentation commune des données dans la mémoire managée et non managée. Quand ces types nécessitent un marshaling, un pointeur vers l’objet dans le tas est passé directement à l’appelé. L’appelé peut changer le contenu de l’emplacement de mémoire référencé par le pointeur.
Remarque
L’appelé peut changer le contenu de la mémoire si le paramètre est marqué « Out » ou « In/Out ». En revanche, l’appelé doit éviter de modifier le contenu quand le paramètre est défini pour marshaler en tant que « In », qui est la valeur par défaut pour les types blittables mis en forme. La modification d’un objet In génère des problèmes lorsque la même classe est exportée vers une bibliothèque de types et utilisée pour effectuer des appels inter-appartements.
Classes non blittables mises en forme
Les classes non blittables mises en forme ont une disposition fixe (mise en forme), mais la représentation des données est différente en mémoire managée et non managée. Les données peuvent nécessiter une transformation dans les conditions suivantes :
Si une classe non blittable est marshalée par valeur, l’appelé reçoit un pointeur vers une copie de la structure de données.
Si une classe non blittable est marshalée par référence, l’appelé reçoit un pointeur vers un pointeur vers une copie de la structure de données.
Si l’attribut InAttribute est défini, cette copie est toujours initialisée avec l’état de l’instance, en marshalant si nécessaire.
Si l’attribut OutAttribute est défini, l’état est toujours recopié dans l’instance au retour, en marshalant si nécessaire.
Si InAttribute et OutAttribute sont définis, les deux copies sont requises. Si l’un ou l’autre attribut est omis, le marshaller peut optimiser en supprimant l'une ou l'autre des copies.
Types référence
Les types référence peuvent être passés par valeur ou par référence. Quand ils sont passés par valeur, un pointeur vers le type est passé sur la pile. Quand ils sont passés par référence, un pointeur vers un pointeur vers le type est passé sur la pile.
Les types de référence ont le comportement conditionnel suivant :
Si un type référence est passé par valeur et possède des membres de types non blittables, les types sont convertis deux fois :
Quand un argument est passé vers le côté non managé.
Lors du retour de l’appel.
Pour éviter de copier et de convertir sans nécessité, ces types sont transférés en tant que paramètres In. Vous devez appliquer explicitement les attributs InAttribute et OutAttribute à un argument pour que l’appelant affiche les modifications apportées par l’appelé.
Si un type référence est passé par valeur et a seulement des membres de types blittables, ce type peut être épinglé lors du marshaling et tout changement apporté par l’appelé aux membres du type est vu par l’appelant. Appliquez explicitement InAttribute et OutAttribute si vous souhaitez ce comportement. Sans ces attributs directionnels, le marshaleur d’interopérabilité n’exporte pas d’informations directionnelles vers la bibliothèque de types (il exporte en tant que « In », ce qui est la valeur par défaut) : ceci peut poser des problèmes lors du marshaling entre cloisonnements COM.
Si un type référence est passé par référence, il est marshalé par défaut en tant que « In/Out ».
System.String et System.Text.StringBuilder
Quand des données sont marshalées vers du code non managé par valeur ou par référence, le marshaleur copie généralement les données vers une mémoire tampon secondaire (en convertissant éventuellement des jeux de caractères lors de la copie) et passe à l’appelé une référence à la mémoire tampon. Sauf si la référence est une BSTR allouée avec SysAllocString, la référence est toujours allouée avec CoTaskMemAlloc.
Par souci d’optimisation quand String ou StringBuilder est marshalé par valeur (comme une chaîne de caractères Unicode), le marshaleur passe à l’appelé un pointeur direct vers des chaînes managées dans la mémoire tampon Unicode interne au lieu de le copier dans une nouvelle mémoire tampon.
Avertissement
Quand une chaîne est passée par valeur, l’appelé ne doit jamais changer la référence passée par le marshaleur. Sinon, il risque d’endommager le tas managé.
Quand une System.String est passée par référence, le marshaleur copie le contenu de la chaîne dans une mémoire tampon secondaire avant d’effectuer l’appel. Il copie ensuite le contenu de la mémoire tampon dans une nouvelle chaîne à la fin de l'appel. Cette technique garantit que la chaîne managée immuable reste inchangée.
Lorsqu’une System.Text.StringBuilder est passée par valeur, le marshaller transmet une référence à une copie temporaire du buffer interne du StringBuilder à l’appelant. L’appelant et l’appelé doivent accepter la taille de la mémoire tampon. L’appelant est responsable de la création d’un StringBuilder de longueur adéquate. L’appelé doit prendre les précautions nécessaires pour garantir le non-débordement de la mémoire tampon.
StringBuilder est une exception à la règle qui stipule que les types de référence passés par valeur sont par défaut passés en tant que In paramètres.
StringBuilder est toujours passé en tant que In/Out.