RT,既然是实现就说说怎么弄一个出来。
(说明:鉴于作者精神问题,基本胡扯)
零、无药可救了,为毛要从0开始,强迫症典型,要电。
不过话说优秀的程序员都是强迫症患者,这个我到有点自(我欣)慰。
首先看看linux下倒是有不少dict,但是android开源的真没有找到,找了半天懒得再去找了,不如自己弄一个算了。
一、老规矩:先说思路,思路正确其他都是体力活。
dict嘛,基本的功能无非就是一个dict+一个查询算法。linux下面开源词典多的是,既然不是做研究,而是为了应付工作,那么不用开源的反而显得自己有些2.
首选的是从sdcv来移植一个,why?如下:
哥从事开源软件(基本是索取)多年,用stardict多年,vim绑的都是sdcv(stardict console version)
如下脚本:
map ? <ESC>:!sdcv <cword><CR>
只要在要查询的单词上敲个?,就可以看到单词解释了。
一句话,感情啊,哥是一个重情谊的人。
二、怎么整?
既然有了目标从sdcv开搞,有几条路可以选
1 看懂sdcv,然后用java仿一个出来(哥不是QQ没有血轮眼,自己写还不累死我?我这么懒会自己写?)
2 jni
由于sdcv深度绑glib,tmd,不得不派生2个选择
2.1 移植一个glib (可行,网上有介绍,也有开源项目,但是活跃度不高,估计也麻烦,想想头疼。另外,更重要的一点:把一个glib绑定到我的小dict中怎么感觉那么别扭呢?
唉,又tm是强迫症)
2.2 去glib,(这个当然可行,说白了,就是把glib的代码copy过来一起编译,就是一个蛋疼的重复劳动,但是难度最小,不打差的话,2天足够了。)
那么我就选择最2b的2.2吧,2.1等哥有空了在玩玩。
三、一个无聊的,2B的过程。
1 提取Makefile中编译命令,精简到无法再精简
g++ -DLOCALEDIR=\"/usr/local/share/locale\" -I. -I/usr/include/glib-2.0 -I/usr/lib/i386-linux-gnu/glib-2.0/include -Ilib -g3 -c -o sdcv.o sdcv.cpp
g++ -DLOCALEDIR=\"/usr/local/share/locale\" -I. -I/usr/include/glib-2.0 -I/usr/lib/i386-linux-gnu/glib-2.0/include -Ilib -g3 -c -o libwrapper.o libwrapper.cpp
。。。。。
g++ -g3 -o sdcv *.o lib/*.o -lz -lglib-2.0
得出可以运行的sdcv。
2 去掉: -lglib-2.0,这个glib库。重新编译sdcv,当然,一堆undefine。别怕,这些undefine就是你这2天要搬运的沙,IT民工嘛,不干干这些体力活,怎么体现打字速度这么大的优势?
找到glib代码中的相应函数,copy到相应undefine的代码中,rebuild,。。。。 不断重复这个过程,知道最后一个undefine也没有了。而且编译出来的sdcv运行ok。
ok,到这里应该已经过了1,2天了,别告诉哥,你半天就把那些undefine函数都替换了。
(注:以上2的方法,如其名,是一个非常非常2的方法,千万别tm把这个当成多好玩的事情!!,不得已的情况下,玩几次可以,你要的是理解代码运行,库依赖的关系即可。而不是享受这个唯一好处是锻炼手指肌肉的过程。这种事情一旦我们可以反抗就不要享受了)
3 到这里,你的无glib依赖的sdcv版本已经ok,next,我们要用jni来封装一下这些c++代码。
1、Android支持JNI,支持C++代码,但如果需要STL(这个是什么玩意?)需要:在jni目录建立Application.mk文件,输入: APP_STL := gnustl_static
$cat Application.mk
APP_STL := gnustl_static
$
2、你需要知道怎么用Andorid的JNI在Java和C代码之间传递数据,我们直接用hello-jni做模板套代码:omit
3、 sdcv的代码是C++的,而我们选择的hello-jni,是C code,所以需要在sdcv.cpp中把我们需要的接口 extern ”C" {}导出(其实就是demangle)
实际上,这里需要修改一下sdcv的输出,毕竟sdcv是输出到console的,我们需要接管他的printf(),把输出format 成我们的格式传递给JNI的接口函数。
哥为了偷懒就直接传string了。在sdcv的lib类加一个std::string result SetResult(),GetResult(),在所有printf()结果的地方直接调用SetResult(),在C++的接口函数GetResult()传递给JNI代码。具体就那么几行代码,omit。
四、debug,对,单独说debug。
纯android开发,eclipse的debug灰常好用
纯linux 代码的debug,自从有了cgdb,也灰常好用。
那么2者结合,就是JNI的debug了。(当然gdb显然没有cgdb好用,不过基本原理都一样)
[·一个窍门就是:先在android代码中下个break,然后在"工程目录"ndk-gdb,下好break,然后continue,再回到android层面操作即可。]
五、说那么多废话,其实没有什么有技术含量的东西。
弄这玩意,一个是我们的项目可能会用到一个dict,先自己预研一下,先把基调定高点,省得被那帮吃货用垃圾来忽悠。
另外一个是:为有需要的小朋友提供点思路,告诉大家至少有一条路是可行的。(大大们就见笑了)
六、//TODO:
stardict的算法和词库的结构