


Modifier une couche d’encapsulation managée et sa bibliothèque native sans casser l’ABI
Pour éditer une surcouche managée multiplateforme sur une bibliothèque C native. Suit chaque changement couche par couche, compile les binaires natifs depuis la source sans téléchargements périmés, garde l’ABI stable, gère la propriété des pointeurs et les threads et ne saute aucun échec.
Pour utiliser ces règles d'IA
## Suivre chaque changement de la couche managée jusqu’au code natif
Traitez la bibliothèque comme un système en couches : encapsulation managée, déclarations d'interopérabilité, API stable compatible avec C et implémentation native.
- Validez les entrées publiques dans la couche d'encapsulation managée.
- Gardez la passerelle compatible avec C petite et prévisible ; elle doit traduire et transmettre, sans dupliquer les règles.
- Maintenez une correspondance exacte entre les déclarations managées, les symboles C exportés, les types de paramètres, les types de retour et les implémentations natives.
- Avant de modifier le code, déterminez quelle couche est responsable de chaque règle de validation, allocation, conversion d'erreur et transition de cycle de vie.
- Suivez une modification dans toutes les couches concernées au lieu de corriger uniquement la première erreur de compilation.
Une modification qui se compile dans la couche managée peut encore échouer à l'exécution si le binaire natif ne contient pas le nouveau symbole ou utilise une signature différente.
## Choisir des binaires natifs précompilés ou compilés depuis la source selon le changement
Les binaires natifs doivent exister avant la compilation de la couche d'encapsulation managée, mais leur source correcte dépend de ce qui a été modifié.
- Pour un travail exclusivement managé, utilisez les artefacts natifs précompilés approuvés par le dépôt pour le jalon publié actuel.
- Pour toute modification de l'implémentation native, de l'API C, des dépendances, d'un sous-module, d'une version ou d'un jalon, compilez les binaires natifs depuis les sources pour la plateforme et l'architecture cibles.
- Après toute modification touchant la partie native, le téléchargement des binaires précompilés actuels est interdit jusqu'à ce que ces modifications soient publiées dans la source d'artefacts.
- Si la compilation native depuis les sources échoue, diagnostiquez les prérequis liés aux outils, aux dépendances, aux chemins ou au réseau. Ne revenez jamais à des téléchargements obsolètes uniquement pour faire réussir la compilation managée.
- Nettoyez les caches de plateforme lorsqu'ils peuvent conserver un ancien module natif et produire de faux résultats de test.
L'utilisation de binaires natifs obsolètes après une modification d'API peut produire une compilation silencieusement incorrecte, puis des erreurs de point d'entrée introuvable à l'exécution.
## Régénérer les liaisons au lieu de les modifier et garder l’ABI stable
Ne modifiez jamais manuellement les liaisons générées, la documentation générée, les pages de version produites ni toute autre sortie déclarée comme générée. Modifiez la source éditable et exécutez le générateur du dépôt après toute modification de l'API C.
Maintenez une interface binaire d'application stable :
- Ajoutez des surcharges, des méthodes ou des types au lieu de modifier les signatures existantes.
- Ne supprimez aucune API publique et ne changez pas ses types de retour.
- Préférez les surcharges aux nouveaux paramètres par défaut, car ceux-ci peuvent modifier la compatibilité binaire.
- Dépréciez une API au lieu de la supprimer et fournissez des consignes de migration applicables.
- Maintenez les conventions de nommage et de paramètres cohérentes avec les API publiques environnantes.
- Régénérez les liaisons et vérifiez les différences obtenues avant de compiler.
Lorsque la documentation comprend des pages générées et des sources auxiliaires éditables, ne modifiez que la source désignée, puis produisez de nouveau la sortie.
## Classer la propriété des pointeurs natifs et ne pas partager d’objets modifiables entre threads
Classez chaque pointeur natif avant d'écrire une couche d'encapsulation :
- Un paramètre emprunté ne transfère pas la propriété.
- Un objet natif détenu manuellement nécessite le chemin de libération native de la couche d'encapsulation.
- Un objet à comptage de références doit suivre le contrat de comptage de références de la couche d'encapsulation.
Adaptez le comportement en cas d'échec à la couche concernée. L'API compatible avec C renvoie un pointeur nul ou `false` ; une fabrique managée renvoie `null` ; un constructeur managé lève une exception lorsqu'il ne peut pas établir un objet valide.
Certaines opérations natives peuvent renvoyer la même instance que celle reçue. Comparez les identités avant de libérer la source ; sinon, la valeur renvoyée pourrait référencer un objet déjà libéré.
Ne partagez pas d'objets natifs mutables entre des threads, sauf si le contrat natif l'autorise explicitement. Donnez à chaque thread son propre état mutable ; ne partagez que les objets documentés comme immuables et sûrs entre threads.
Ne transmettez jamais à du code natif un pointeur managé temporairement fixé si ce code peut le conserver au-delà de la portée de fixation. Utilisez un handle fixé avec une durée de vie explicite ou allouez de la mémoire non managée. Enfreindre cette règle permet au ramasse-miettes de déplacer la mémoire alors que le code natif conserve encore l'ancienne adresse.
## Utiliser des branches de fonctionnalité dans le dépôt parent et le sous-module natif
Créez une branche de fonctionnalité avant d'enregistrer des commits. N'enregistrez jamais directement des modifications dans une branche protégée.
Appliquez la même règle indépendamment à un sous-module natif ou à un dépôt imbriqué : il possède son propre état de branches, ses branches protégées, ses commits et son parcours de révision.
1. Créez une branche de fonctionnalité ciblée dans le dépôt parent.
2. Si le dépôt natif imbriqué change, créez-y sa branche de fonctionnalité avant toute modification ou tout commit.
3. Conservez tous les commits dans les branches de fonctionnalité correspondantes.
4. Soumettez les modifications à révision au moyen du processus de demande d'intégration approuvé par le dépôt.
5. Vérifiez que le dépôt parent référence la révision native prévue et déjà révisée.
Ne modifiez pas les répertoires natifs gérés par le projet d'origine en dehors de la surface d'adaptation ou d'extension déclarée par le dépôt.
## Tester avec les bons binaires natifs sans ignorer les échecs
Une compilation réussie ne constitue pas l'achèvement. Exécutez les tests managés pertinents avec des binaires natifs produits par le bon chemin d'amorçage.
- Les tests doivent réussir avant toute déclaration d'achèvement.
- N'ignorez pas un test en échec et n'introduisez pas d'exception d'ignorance pour contourner une régression.
- Un test ne peut être ignoré qu'en raison d'une limitation matérielle ou de plateforme démontrée, par exemple l'absence d'écran, l'indisponibilité d'un périphérique graphique ou une fonctionnalité non prise en charge par la plateforme.
- Régénérez les liaisons avant les tests lorsque l'API C a changé.
- Nettoyez les artefacts natifs web ou de plateforme mis en cache avant de valider les changements de version.
- Vérifiez des plateformes et architectures représentatives pour les travaux qui affectent la partie native.
Écrivez des tests qui échouent lorsque la propriété, la gestion des valeurs nulles, les symboles exportés, l'ABI, la portée des threads ou la libération sont incorrects. Incluez des tests de parité et des mesures de performance pour les changements de performance lorsque le comportement exact ou le bénéfice n'est pas encore démontré.
## Repérer les erreurs entre couches à partir de la forme de l’échec
Établissez un état de référence connu comme valide, ne modifiez qu'une variable à la fois, consignez chaque résultat et traitez les différences entre plateformes comme des éléments de preuve. Si une modification dégrade l'état, annulez-la avant de tester une autre hypothèse.
Utilisez la forme de l'échec pour choisir la première frontière à examiner :
- Un type managé manquant suggère que les liaisons n'ont pas été régénérées ou incluses.
- Un symbole natif non résolu suggère une divergence entre la déclaration C et l'implémentation.
- Un point d'entrée manquant à l'exécution indique fortement des binaires natifs obsolètes ou une exportation non concordante.
- Une violation d'accès suggère une corruption de la propriété, de la libération, de la fixation ou de la signature.
- Un échec de référence nulle après un appel de fabrique suggère que la couche native a renvoyé un échec et que l'appelant l'a ignoré.
- Des arrêts aléatoires entre threads suggèrent que des objets natifs mutables ont été partagés.
Avant de terminer, examinez les différences générées, compilez le code natif si nécessaire, compilez la couche d'encapsulation managée, exécutez les tests et vérifiez la matrice des plateformes concernées. Indiquez la source et l'architecture exactes utilisées pour l'amorçage. Ne déclarez pas de réussite si des tests échouent, si les compilations natives requises ont été remplacées par des téléchargements ou si la vérification des plateformes reste incomplète.
