5

背景

FreeLing API 定义了一个不遵循标准 Java 命名约定的接口例如:

package freeling;

public class sentence extends ListWord {
  public void set_parse_tree(parse_tree arg0) {

该接口使用SWIG定义,类似于IDL

class sentence : public std::list<word> {
 public:
  sentence(void);

  void set_parse_tree(const parse_tree &);

问题

从学术上讲,您如何将接口映射到传统的 Java 命名标准(例如,class SentencesetParseTree( parseTree arg0 ))?

想法

  1. 手动转换 650+ 行接口文件(并将补丁发送给开发人员)。
  2. 正则表达式搜索和替换voodoo(使用 vi)::1,$s/_\([a-z]\)/\u\1/g
  3. 从 53 个自动生成的 Java 源文件创建包装类。

谢谢!

4

3 回答 3

5

SWIG 提供了一个%rename指令,允许名称在客户端和实现语言中不同。 但是这样做会使接口文件的长度几乎增加一倍。

实际上,SWIG 提供批量重命名。请参阅文档

5.4.7.2 高级重命名支持

虽然为特定声明编写 %rename 很简单,但有时需要将相同的重命名规则应用于 SWIG 输入中的许多(可能是全部)标识符。例如,可能需要对目标语言中的所有名称进行一些转换,以更好地遵循其命名约定,例如为所有包装函数添加特定前缀。为每个函数单独执行此操作是不切实际的,因此如果未指定要重命名的标识符的名称,SWIG 支持将重命名规则应用于所有声明:

%rename("myprefix_%s") ""; // print -> myprefix_print

这也表明 %rename 的参数不必是文字字符串,也可以是类似 printf() 的格式字符串。在最简单的形式中,“%s”被替换为原始声明的名称,如上所示。然而,这并不总是足够的,SWIG 提供了对常用格式字符串语法的扩展,以允许将(SWIG 定义的)函数应用于参数。例如,要将所有 C 函数 do_something_long() 包装为更像 Java 的 doSomethingLong() ,您可以使用“lowercamelcase”扩展格式说明符,如下所示:

%rename("%(lowercamelcase)s") ""; // foo_bar -> fooBar; FooBar -> fooBar

一些函数可以参数化,例如“strip”从它的参数中去除提供的前缀。前缀被指定为格式字符串的一部分,紧跟在函数名后面的冒号后面:

%rename("%(strip:[wx])s") ""; // wxHello -> Hello; FooBar -> FooBar

我的建议是保持原样。您正在调用 C++ 函数,它们具有 C++ 名称。如果有的话,这可以帮助您记住您正在调用 C++ 并且需要遵循 C++ 规则进行对象生命周期管理,还有轻微的 JNI 性能损失等。

于 2012-05-28T22:38:33.750 回答
1

你知道你不应该用正则表达式解析 HTML 吗?是的,也不要用正则表达式编写编译器级逻辑。所以不是(2)。

不要重写他们的界面。他们的代码需要它以及您可能使用的其他中间库。不是(1)。

如果您想将丑陋的代码排除在代码之外,请编写一个包装器接口。这样,在向他们发送一封礼貌的信之后,或者换成由更严格遵守约定的开发人员制作的库之后,您就可以灵活地进行迁移。

于 2012-05-28T22:27:13.280 回答
0

在尝试集成 FreeLing JNI API 时,我遇到了同样的命名约定危机,然后我意识到这个 API 让我在项目的编译周期中遇到困难,而且性能方面远非最佳(因为它在内部重新创建所有对象你提交的每一句话)。我建议您切换到捆绑包中的分析器服务器:客户端/服务器模式文档

您可以重新创建他们在 PHP 示例和Analyzer.cc中实现的内容。

于 2012-06-15T09:20:54.107 回答