2 votes

Implémentation et compatibilité binaire

J'ai une DLL VB6 ActiveX qui expose une classe INewReport . J'ai ajouté quelques nouvelles méthodes à cette classe et j'ai pu la reconstruire en conservant la compatibilité binaire.

J'ai une deuxième DLL qui expose une classe clsNewReport qui met en œuvre la première classe en utilisant :

Implements RSInterfaces.INewReport

Depuis que j'ai ajouté de nouvelles méthodes à INewReport j'ai également dû ajouter ces nouvelles méthodes à l'ensemble de l'UE. clsNewReport .

Cependant, lorsque j'essaie de compiler la deuxième DLL, je reçois l'erreur de compatibilité binaire suivante "...une classe a implémenté une interface dans le composant compatible avec la version, mais pas dans le projet actuel" .

enter image description here

Je ne suis pas sûr de ce qui se passe ici. Puisque je ne fais qu'ajouter à la classe, pourquoi ne puis-je pas maintenir la compatibilité binaire avec la deuxième DLL ? Existe-t-il un moyen de contourner ce problème ?

2voto

DaveInCaz Points 2681

Je pense qu'il s'agit d'une explication correcte de ce qui se passe, et de quelques solutions de contournement potentielles.

J'ai créé un cas de test qui reproduit le problème dans la description et j'ai ensuite vidé l'IDL en utilisant OLEView à partir de l'ancienne et de la nouvelle DLL qui contenait l'interface.

Voici une comparaison de l'ancienne (à gauche) et de la nouvelle IDL de INewReport :

enter image description here

Des différences importantes :

  • L'UUID de interface _INewReport a modifié

  • Un typedef appelé INewReport___v0 a été ajouté, qui fait référence à la original UUID de l'interface

(Je suppose que c'est également ce qui se passe pour le code mentionné dans la question).

Ainsi, dans le projet client, la DLL bincomp fait référence à l'UUID de l'interface originale, mais cet UUID ne correspond qu'à un nom différent ( INewReport___v0 au lieu de INewReport ) qu'à l'origine. Je pense que c'est la raison pour laquelle VB6 pense qu'il y a une incompatibilité de bincomp.


Comment résoudre ce problème ? Je n'ai pas pu faire quoi que ce soit en VB6 qui vous permette d'utiliser la DLL d'interface mise à jour avec le code client sans avoir à casser la bincomp du code client.

Une (mauvaise) option pourrait être de simplement changer la DLL du client pour utiliser la compatibilité du projet... mais cela peut ou non être acceptable dans votre cas. Cela pourrait causer la rupture de tout ce qui utilise la DLL du client, à moins que tous les consommateurs soient également recompilés. (Et cela pourrait potentiellement causer une cascade de bincomp cassés).

Une option meilleure mais plus complexe serait de définir l'interface dans IDL lui-même, d'utiliser le compilateur MIDL pour générer un typelib (fichier TLB) et de le référencer directement. Vous auriez alors un contrôle total sur le nommage de l'interface, etc. Vous pourriez utiliser l'IDL généré par OLEView comme point de départ pour réaliser cette opération.

Cette deuxième option suppose que la classe d'interface n'est réellement qu'une interface et qu'elle ne contient aucun code fonctionnel.


Voici comment j'ai configuré un cas pour reproduire ce problème :

Étape 1. Définition de l'interface originale - classe appelée INewReport défini comme compatible binaire :

Sub ProcA()    
End Sub    

Sub ProcB()    
End Sub

Étape 2. Créez une DLL de client de test qui met en œuvre les éléments suivants INewReport qui est également compatible avec le système binaire :

Implements INewReport    

Sub INewReport_ProcA()    
End Sub

Sub INewReport_ProcB()    
End Sub

Étape 3 : Ajouter ProcC a INewReport et recompiler (ce qui enregistre également la DLL nouvellement construite) :

(code ci-dessus, plus :)

Sub ProcC()    
End Sub    

Étape 4 : Essayez d'exécuter ou de compiler la DLL du client de test - vous obtenez instantanément l'erreur du PO. Il n'est pas nécessaire de modifier les références ou quoi que ce soit d'autre.

1voto

BobRodes Points 592

J'ai pu recréer votre problème, en utilisant quelque chose de similaire au code de DaveInCaz. J'ai essayé un certain nombre de choses pour le résoudre, en répétant probablement des choses que vous avez déjà essayées. Je suis arrivé à une hypothèse possible sur la raison pour laquelle cela se produit. Cela ne résout pas le problème, mais cela peut apporter un éclairage supplémentaire.

Citation de Cette page de document :

Pour assurer la compatibilité, Visual Basic impose certaines restrictions aux modifications que vous apportez aux interfaces par défaut. Visual Basic vous permet d'ajouter de nouvelles classes, et d'améliorer l'interface par défaut de toute classe existante en ajoutant des propriétés et des méthodes. Si vous supprimez des classes, des propriétés ou des méthodes, ou si vous modifiez les arguments des propriétés ou des méthodes existantes, Visual Basic émettra des avertissements d'incompatibilité.

Une autre citation :

La règle ActiveX que vous devez suivre pour assurer la compatibilité avec plusieurs interfaces est simple : une fois qu'une interface est utilisée, elle ne peut jamais être changée. . L'ID d'interface d'une interface standard est fixé par la bibliothèque de types qui définit l'interface.

Donc, voici une hypothèse. La première citation mentionne le par défaut ce qui suggère qu'il n'est peut-être pas possible de modifier les interfaces personnalisées de quelque manière que ce soit. C'est également ce que suggère la deuxième citation. Vous êtes en mesure de modifier la classe d'interface, car vous modifiez essentiellement son interface par défaut. Cependant, lorsque vous tentez de modifier la classe d'implémentation en conséquence, pour refléter les modifications de votre interface, votre référence d'implémentation pointe vers l'ancienne version de l'interface, qui n'existe plus. Bien sûr, le message d'erreur ne fait aucune allusion à cela, car il semble être basé sur l'idée que vous n'avez pas essayé d'implémenter l'interface.

Je n'ai pas été en mesure de le prouver, mais en regardant la réponse de DaveInCaz, le fait que l'UUID ait changé semble confirmer cette idée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X