Prise en charge de plusieurs versions incompatibles de la bibliothèque C ++

StackOverflow https://stackoverflow.com/questions/9464985

  •  13-11-2019
  •  | 
  •  

Question

J'ai écrit Une extension Ruby C ++ Envelopper Bibliothèque d'expression régulière de Google de Google Mais un Mise à jour récente de la bibliothèque a changé l'interface du Match() Fonction de:

bool Match(const StringPiece& text,
           int startpos,
           Anchor anchor,
           StringPiece *match,
           int nmatch) const;

À:

bool Match(const StringPiece& text,
           int startpos,
           int endpos,
           Anchor anchor,
           StringPiece *match,
           int nmatch) const;

(Notez le nouveau int endpos dispute.)

Ma question est: est-il possible pour moi de prendre en charge les deux versions de cette bibliothèque dans une extension malgré le fait que RE2 ne semble pas spécifier une sorte de VERSION constant que je peux introspecter?

Idéalement, je veux pouvoir essayer la version plus récente (avec 6 arguments) et, à défaut, retomber à l'ancienne version (car je suis en mesure de remplir le remplissage du endpos argument facilement).

Pour le moment, mon code est comme ceci:

matched = p->pattern->Match(text_as_string_piece, 0, (int)RSTRING_LEN(text), RE2::UNANCHORED, 0, 0);

Mais si vous avez l'ancienne version de RE2, cela doit être:

matched = p->pattern->Match(text_as_string_piece, 0, RE2::UNANCHORED, 0, 0);
Était-ce utile?

La solution

La réponse traditionnelle est de générer un config.h ou quoi que ce soit au moment de l'installation.

Autrement dit, lors de l'installation, vous détecrez quelle version de re2 est installé, puis définissez un symbole dans config.h Selon ceci:

// config.h
#ifndef CONFIG_H_INCLUDED
#define CONFIG_H_INCLUDED

#define RE2_MATCH_6_ARGS 1

#endif // CONFIG_H_INCLUDED

Et puis, vous pouvez utiliser ceci:

#if defined(RE2_MATCH_6_ARGS) && RE2_MATCH_6_ARGS == 1
  matched = p->pattern->Match(text_as_string_piece, 0, (int)RSTRING_LEN(text), RE2::UNANCHORED, 0, 0);
#else
  matched = p->pattern->Match(text_as_string_piece, 0, RE2::UNANCHORED, 0, 0);
#endif

Il s'agit d'une solution stable et devrait bien fonctionner.


Une autre possibilité est de pirater le système ...

Fournir une définition des deux Match Fonctions dans une bibliothèque wrapper:

  • Match5 lance une erreur (veuillez créer un lien vers RE2)
  • Match6 en avant Match5.

La chose est (dans le monde Unix ...), si un symbole a déjà été chargé, il ne sera pas écrasé par une nouvelle définition. Donc tant que re2 est chargé en premier, vous vous retrouvez dans l'un de ces deux scénarios:

  • Agé de re2: votre bibliothèque (wrapper) fournit une définition de Match6 qui transmet au re2 a fourni une définition de Match5
  • Nouveau re2: l'appel va directement à la définition de Match6 ce re2 fourni

Beaucoup plus cassant. Nécessite un bibliothèque wrapper autour de re2. Il est peu probable qu'il travaille avec une liaison statique (jamais essayé cependant ...). Mais ne nécessite pas un ./configure marcher.

Autres conseils

D'après ce que je sais, vous ne pouvez pas. Cela vous obligerait à créer un lien avec les anciennes et les nouvelles versions de RE2, ce qui ferait entrer en collision les espaces de noms.

À moins qu'il existe une version de cette méthode qui reçoit l'ancienne version, vous êtes coincé avec la nouvelle version.

Si vous voulez pouvoir compiler Votre extension pour les deux versions, alors vous devez modifier vos étapes de compilation pour définir un drapeau tu contrôler.

#ifdef RE2_ODLFORMAT
matched = p->pattern->Match(text_as_string_piece, 0, RE2::UNANCHORED, 0, 0);
#else
matched = p->pattern->Match(text_as_string_piece, 0, (int)RSTRING_LEN(text), RE2::UNANCHORED, 0, 0);
#endif

Ensuite, pour compiler votre code, vous feriez quelque chose dans ce sens:

make RE2_OLDFORMAT=1 all # compile for old version
make all # default target is for new version
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top