Prise en charge de plusieurs versions incompatibles de la bibliothèque C ++
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);
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 avantMatch5
.
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 deMatch6
qui transmet aure2
a fourni une définition deMatch5
- Nouveau
re2
: l'appel va directement à la définition deMatch6
cere2
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