以编程方式切换 API 命名约定

Dav*_*vis 5 c++ java vim swig naming-conventions

背景

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

package freeling;

public class sentence extends ListWord {
  public void set_parse_tree(parse_tree arg0) {
Run Code Online (Sandbox Code Playgroud)

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

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

  void set_parse_tree(const parse_tree &);
Run Code Online (Sandbox Code Playgroud)

问题

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

想法

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

谢谢你!

Ben*_*igt 5

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

实际上,SWIG 提供批量重命名。查看文档

5.4.7.2 高级重命名支持

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

%rename("myprefix_%s") ""; // print -> myprefix_print
Run Code Online (Sandbox Code Playgroud)

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

%rename("%(lowercamelcase)s") ""; // foo_bar -> fooBar; FooBar -> fooBar
Run Code Online (Sandbox Code Playgroud)

有些函数可以参数化,例如“strip”函数从其参数中删除提供的前缀。前缀被指定为格式字符串的一部分,位于函数名称后面的冒号后面:

%rename("%(strip:[wx])s") ""; // wxHello -> Hello; FooBar -> FooBar
Run Code Online (Sandbox Code Playgroud)

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

  • @戴夫:哇。我不敢相信您正在使用 C++ 代码,并对 RAII 存在如此根本的误解。但这也许就是 SWIG 让包装变得简单的缺点。我希望该库永远不会打开文件,或使用任何其他需要按时释放/关闭的共享资源。 (3认同)