背景
FreeLing API 定义了一个不遵守标准 Java 命名约定的接口(interface)。例如:
package freeling;
public class sentence extends ListWord {
public void set_parse_tree(parse_tree arg0) {
接口(interface)是使用SWIG定义的,类似于 IDL :
class sentence : public std::list<word> {
public:
sentence(void);
void set_parse_tree(const parse_tree &);
问题
从学术上讲,您如何将接口(interface)映射到传统的 Java 命名标准(例如,class Sentence
和 setParseTree( parseTree arg0 )
)?
想法
- 转换 650+ 行 interface file手动(并向开发人员发送补丁)。
- 正则表达式 search and replace voodoo(使用 vi):
:1,$s/_\([a-z]\)/\u\1/g
- 从 53 个自动生成的 Java 源文件创建包装器类。
谢谢!
最佳答案
SWIG 提供了一个 %rename
指令,允许在客户端和实现语言中使用不同的名称。 但这样做会使接口(interface)文件的长度增加近一倍。
实际上,SWIG 提供了批量重命名。参见 the documentation
5.4.7.2 Advanced renaming support
While writing %rename for specific declarations is simple enough, sometimes the same renaming rule needs to be applied to many, maybe all, identifiers in the SWIG input. For example, it may be necessary to apply some transformation to all the names in the target language to better follow its naming conventions, like adding a specific prefix to all wrapped functions. Doing it individually for each function is impractical so SWIG supports applying a renaming rule to all declarations if the name of the identifier to be renamed is not specified:
%rename("myprefix_%s") ""; // print -> myprefix_print
This also shows that the argument of %rename doesn't have to be a literal string but can be a printf()-like format string. In the simplest form, "%s" is replaced with the name of the original declaration, as shown above. However this is not always enough and SWIG provides extensions to the usual format string syntax to allow applying a (SWIG-defined) function to the argument. For example, to wrap all C functions do_something_long() as more Java-like doSomethingLong() you can use the "lowercamelcase" extended format specifier like this:
%rename("%(lowercamelcase)s") ""; // foo_bar -> fooBar; FooBar -> fooBar
Some functions can be parametrized, for example the "strip" one strips the provided prefix from its argument. The prefix is specified as part of the format string, following a colon after the function name:
%rename("%(strip:[wx])s") ""; // wxHello -> Hello; FooBar -> FooBar
我的建议是保持原样。您正在调用 C++ 函数,它们具有 C++ 名称。如果有的话,这可以帮助您记住您正在调用 C++ 并且需要遵循 C++ 对象生命周期管理规则,JNI 性能会受到轻微影响,等等。
关于java - 以编程方式切换 API 命名约定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10790795/