SRILM的java接口

0. 前言

最近工作的需要,需要讲SRILM通过JNI编译到Java程序中,一直没有找到一个完成的教程,遇到不少坑,特此整理,帮助大家少走弯路,不用各处去找,一篇文章解决问题。这里提供Mac和Linux两种系统的说明,请大家按照各自的系统进行。

1. SRILM的安装

SRILM的下载链接为http://www.speech.sri.com/projects/srilm/download.html 这里用的版本为1.7.1,创建安装的目录,假设安装目录为:$SRILM_HOME。
   在编译之前,需要修改一下的几个地方:
   1. 修改根目录的Makefile文件,添加一行SRILM = $SRILM_HOME,把SRILM在本地的位置写上。
   2. 同样在根目录的Makefile文件,找到MACHINE_TYPE := $(shell $(SRILM)/sbin/machine-type)这一行,如果是Mac电脑,那么将这个注释掉,加一行MACHINE_TYPE := macosx-m64(如果32位那就写32);如果是Linux,那么不需要注释,基本会自动识别的。
   3. 这个需要修改在common目录下的文件,如果是Mac系统,那么需要修改Makefile.machine.macosx,如果是Linux系统,需要根据你的系统情况找到对应的文件,查看系统情况使用uname -a命令。修改的内容均一样,找到GCC_FLAGS = -Wall -Wno-unused-variable -Wno-uninitialized -Wno-overloaded-virtual这一行,修改为GCC_FLAGS = -Wall -Wno-unused-variable -Wno-uninitialized -Wno-overloaded-virtual -fPIC。这一步很关键,否则会有错。具体解释参见http://blog.csdn.net/u010312436/article/details/52486811。

修改之后,就可以在srilm的目录中输入make World进行编译,编译结束之后,输入make test检查,如果大部分结果都为IDENTITY,那么证明编译成功。

2. 利用JNI生成头文件

这一步就是正常JNI的步骤,首先编写一个类来描述需要写的接口,例子如下
public class LMCaculate {
	// TAG for log.
	private static final String TAG = "LMCaculate";

	// Single Instance.
	private static LMCaculate instance = null;

	// Get instance.
	public static LMCaculate getInstance() {
		if(instance == null) {
			instance = new LMCaculate();
			System.load(Config.LM_jni);
	        instance.init(Config.LM_file, 3);
		}
		return instance;
	}

	public native boolean init(String modelPath, int ngramOrder);

	public native void release();

	public native float calcProbSequence(String wordsSequence, String context);
}

需要接口完成的函数需要添加native标签,这里主要利用三个方法,一个是将lm文件读入内存,另一个是将释放资源,最后是计算语言模型的概率。
随后利用javah命令生成头文件,利用srilm编写对应的cpp文件。

3. 编写makefile文件

得到这两部分内容之后,接下来就是编译的步骤,这里直接将Mac平台和Linux平台的makefile贴出来,大家可以根据自己的情况进行修正。首先是Linux的makefile文件
Srilm_INCLUDE = $SRILM_HOME/include \
-I /usr/lib/jvm/java-7-openjdk-amd64/include

Srilm_LIB = $SRILM_HOME/lib/i686-m64/liboolm.a \
                        $SRILM_HOME/lib/i686-m64/libmisc.a \
                        $SRILM_HOME/lib/i686-m64/liblattice.a \
                        $SRILM_HOME/lib/i686-m64/libflm.a \
                        $SRILM_HOME/lib/i686-m64/libdstruct.a \
                        $SRILM_HOME/lib/i686-m64/libz.a

libCalcSentProb.so: jni.o $(Srilm_LIB)
        g++ -shared -o libCalcSentProb.so jni.o $(Srilm_LIB)  -lpthread -fopenmp
jni.o: jni.cpp
        g++ -fPIC -I $(Srilm_INCLUDE) -c jni.cpp -o jni.o



这里的jni.cpp就是上一步根据jni生成的头文件写的cpp文件
在Mac上的Makefile文件为
Srilm_INCLUDE = $SRILM_HOME/include \
	-I /Library/Java/JavaVirtualMachines/jdk1.8.0_66.jdk/Contents/Home/include \
	-I /Library/Java/JavaVirtualMachines/jdk1.8.0_66.jdk/Contents/Home/include/darwin/

Srilm_LIB = $SRILM_HOME/lib/macosx-m64/liboolm.a \
			$SRILM_HOME/lib/macosx-m64/libmisc.a \
			$SRILM_HOME/lib/macosx-m64/liblattice.a \
			$SRILM_HOME/lib/macosx-m64/libflm.a \
			$SRILM_HOME/lib/macosx-m64/libdstruct.a \
			$SRILM_HOME/lib/macosx-m64/libz.a

libCalcSentProb.dylib: jni.o $(Srilm_LIB) libiconv.dylib
	g++ -shared -o libCalcSentProb.dylib jni.o $(Srilm_LIB) libiconv.dylib
jni.o: jni.cpp
	g++ -fPIC -I $(Srilm_INCLUDE) -c jni.cpp -o jni.o
这里需要说明的是,在Mac中虽然有libiconv.dylib,但是在g++编译的过程中不会自动加入,需要手动从/usr/lib目录中拷贝出来(记得是拷贝,不是剪切!),放在本地目录即可。

通过这种方式就可以获得SRILM的java接口




   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值