Marshaling d'interopérabilité du paramètre de l'assembly de Visual Studio
VSPackages écrits en code managé peut devoir appeler ou être appelé par du code non managé COM. En général, les arguments de méthode sont transformés, ou marshalés, automatiquement par le marshaleur d'interopérabilité. Toutefois, il peut arriver que des arguments ne peuvent pas être transformés de façon simple. Dans ces cas, les paramètres d'interopérabilité du prototype de méthode d'assembly sont utilisés pour correspondre aux paramètres de fonction COM mieux possible. Pour plus d'informations, consultez Marshaling d'interopérabilité.
suggestions générales
lisez la documentation de référence
Un moyen efficace de détecter les problèmes d'interopérabilité consiste à lire la documentation de référence pour chaque méthode.
La documentation de référence pour chaque méthode contient trois sections pertinentes :
Le prototype de fonction de Visual C++ COM.
le prototype d'interopérabilité de méthode d'assembly.
La liste des paramètres COM et d'une brève description de chaque.
recherchez les différences entre les deux prototypes
La plupart des problèmes d'interopérabilité dérivent les incompatibilités entre la définition d'un particulier dans une interface COM et la définition du même type dans les assemblys d'interopérabilité de Visual Studio . Par exemple, considérez la différence dans la possibilité de passer une valeur d' null dans [out] un paramètre. Vous devez rechercher les différences entre les deux prototypes et considérer leurs ramifications les données qui sont passées.
lisez les définitions de paramètre
lisez les définitions de paramètre. COM est moins strict que le common langage runtime (CLR) à propos de combiner des types de données dans un seul paramètre. Les interfaces COM de Visual Studio pleinement parti de cette flexibilité. Tout paramètre qui peut passer ou requiert une valeur non standard ou type de données, tel qu'une valeur de constante dans un paramètre de pointeur, doit être décrit comme tels dans la documentation.
Objets d'IUnknown passés comme de type void **
Recherchez [out] les paramètres définis comme type void ** dans l'interface COM, mais qui sont définis comme [iid_is] dans le prototype d'interopérabilité de méthode d'assembly de Visual Studio .
Parfois, une interface COM génère un objet d' IUnknown , et l'interface COM puis les passe en tant que type void **. Ces interfaces sont particulièrement importantes parce que si la variable est définie par [out] dans le fichier IDL, l'objet d' IUnknown référence-est compté avec la méthode d' AddRef . Une fuite de mémoire se produit si l'objet n'est pas gérées correctement.
Notes
Un objet d' IUnknown créé par l'interface COM et retourner dans [out] une variable entraîne une fuite de mémoire s'il n'est pas explicitement désactivé.
Les méthodes managées qui gèrent de ces objets doivent concerner IntPtr comme pointeur vers un objet d' IUnknown , et appelez la méthode d' GetObjectForIUnknown pour obtenir l'objet. L'appelant doit ensuite caster la valeur de retour à n'importe quel type est approprié. Lorsque l'objet n'est plus nécessaire, appelez Release pour le libérer.
Voici un exemple d'appeler la méthode d' QueryViewInterface et de gérer l'objet d' IUnknown correctement :
MyClass myclass;
Object object;
IntPtr pObj;
Guid iid = Typeof(MyClass).Guid;
int hr = windowFrame.QueryViewInterface(ref iid, out pObj);
if (NativeMethods.Succeeded(hr))
{
try
{
object = Marshal.GetObjectForIUnknown(pObj);
myclass = object;
}
finally
{
Marshal.Release(pObj);
}
}
else
{
// error calling QueryViewInterface
}
Notes
Les méthodes suivantes sont connues pour passer des pointeurs d'objet d' IUnknown comme type IntPtr.Gérez-les comme décrit dans cette section.
paramètres [out] facultatifs
Recherchez les paramètres définis comme [out] type de données (int, object, etc.) dans l'interface COM, mais qui sont définis en tant que tableau du même type de données dans le prototype d'interopérabilité de méthode d'assembly de Visual Studio .
Certaines interfaces COM, telles que l' GetCfgs, traitent [out] les paramètres comme facultatifs. Si un objet n'est pas requis, ces interfaces COM retournent un pointeur d' null comme valeur du paramètre au lieu de [out] créer l'objet. Ce problème est dû au design. Pour ces interfaces, les pointeurs d' null sont assumés dans le cadre de le comportement correct du VSPackage, et aucune erreur n'est retournée.
Étant donné que le CLR ne permet pas à [out] la valeur d'un paramètre en null, une partie du comportement conçu de ces interfaces n'est pas directement disponible dans le code managé. Les méthodes d'interopérabilité d'assembly de Visual Studio pour les interfaces affectées fonctionnent autour de le problème en définissant les paramètres appropriés en tant que tableaux parce que le CLR permet le passage de tableaux d' null .
Les implémentations managées de ces méthodes doivent mettre un tableau d' null dans le paramètre lorsqu'il n'y a aucun élément à être retourné. Sinon, créez un tableau d'un élément du type correct et placez la valeur de retour dans le tableau.
Les méthodes managées qui acceptent les informations des interfaces avec les paramètres facultatifs [out] acceptent le paramètre en tant que tableau. Examinez uniquement la valeur du premier élément du tableau. Si ce n'est pas null, traitez le premier élément comme s'il s'agissait du paramètre d'origine.
Passer des constantes dans les paramètres de pointeur
Recherchez les paramètres définis comme [in] pointeurs dans l'interface COM, mais qui sont définis comme IntPtr dans le prototype d'interopérabilité de méthode d'assembly de Visual Studio .
Un problème similaire se produit lorsqu'une interface COM passe une valeur spéciale, telle que 0, -1, ou - 2, au lieu d'un pointeur d'objet. Contrairement à Visual C++, le CLR ne permet pas aux constantes pour être casté en tant qu'objets. au lieu de cela, l'assembly d'interopérabilité de Visual Studio définit le paramètre comme type d' IntPtr .
Les implémentations managées de ces méthodes doivent tirer parti du fait que la classe d' IntPtr a int et des constructeurs d' void * pour créer IntPtr d'un objet ou d'une constante entière, selon le cas.
Les méthodes managées qui acceptent des paramètres d' IntPtr de ce type doivent utiliser les opérateurs de conversion de type d' IntPtr pour gérer les résultats. Tout d'abord convertir IntPtr à int et testez -le par rapport à les constantes entières appropriées. Si valeur ne correspond, convertissez -la en objet du type requis et continuez.
Pour obtenir des exemples de cela, consultez l' OpenStandardEditor et l' OpenSpecificEditor.
OLE valeurs de retour passées [out] en tant que paramètres
Recherchez les méthodes qui ont une valeur de retour d' retval dans l'interface COM, mais qui ont une valeur de retour d' int et un paramètre supplémentaire [out] de tableau dans le prototype d'interopérabilité de méthode d'assembly de Visual Studio . Il doit être clair que ces méthodes requièrent une gestion spéciale car les prototypes d'interopérabilité de méthode d'assembly de Visual Studio ont un plus de paramètre que les méthodes d'interface COM.
Nombre d'interfaces COM qui traitent OLE activité envoyer des informations sur le OLE état revient au programme appelant enregistré dans la valeur de retour d' retval de l'interface. Au lieu d'utiliser une valeur de retour, les méthodes d'interopérabilité correspondantes d'assembly de Visual Studio envoient des informations sur le programme appelant stocké dans [out] un paramètre de tableau.
Les implémentations managées de ces méthodes doivent créer un tableau à un seul élément du même type que [out] le paramètre et le placer dans le paramètre. La valeur de l'élément de tableau doit être identique à COM approprié retval.
Les méthodes managées appellent des interfaces de ce type doivent extraire le premier élément hors [out] de le tableau. Cet élément peut être traité comme une valeur de retour d' retval de l'interface COM correspondante.
Voir aussi
Tâches
Dépannage des problèmes liés à l'interopérabilité (Visual Basic)