支持多个不兼容的C ++库版本

时间:2012-02-27 12:24:54

标签: c++ re2

我写了a Ruby C++ extension以包裹Google's re2 regular expression library,但recent update to the library更改了Match()函数的界面:

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;

(注意新的int endpos参数。)

我的问题是:我是否有可能在一个扩展中支持这个库的两个版本,尽管re2似乎没有指定任何我可以反省的VERSION常量?

理想情况下,我希望能够尝试更新的版本(带有6个参数),如果失败,则回退到旧版本(因为我能够轻松地回填endpos参数)。

目前我的代码是这样的:

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

但是如果您有旧版本的re2,则需要:

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

2 个答案:

答案 0 :(得分:0)

据我所知,你做不到。这将要求您链接RE2的旧版本和新版本,这将使命名空间发生冲突。

除非存在重新使用旧版本的此方法的版本,否则您将无法使用新版本。

如果您希望能够编译两个版本的扩展,那么您必须修改编译步骤以定义控制的一些标记。

#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

然后要编译代码,你可以按照以下方式做点什么:

make RE2_OLDFORMAT=1 all # compile for old version
make all # default target is for new version

答案 1 :(得分:0)

传统的答案是在安装时生成config.h或其他任何内容。

也就是说,在安装时,您将检测安装了re2的版本,然后在config.h中定义符号,具体取决于:

// config.h
#ifndef CONFIG_H_INCLUDED
#define CONFIG_H_INCLUDED

#define RE2_MATCH_6_ARGS 1

#endif // CONFIG_H_INCLUDED

然后,你可以使用它:

#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

这是一个稳定的解决方案,应该可以正常使用。


另一种可能性就是攻击系统......

在包装器库中提供Match个函数的定义:

  • Match5会抛出错误(请链接到re2)
  • Match6转发至Match5

事情是(在Unix世界中......),如果已经加载了符号,它将不会被新定义覆盖。因此,只要首先加载re2,您就会进入以下两种情况之一:

  • re2:您的(包装)库提供Match6的定义,该定义转发re2提供的Match5定义
  • re2:来电直接转到Match6提供的re2定义

很多更脆弱。需要re2周围的包装器库。不太可能使用静态链接(从未尝试过......)。但不需要./configure步骤。