http://www.kankanews.com/ICkengine/archives/40121.shtml
现在的心情是:真想抬起脚把这电脑一脚踹了
就一个编码问题整整近3个工作日的苦憋 …
把这个苦憋的过程记录下来,也给后来的朋友做个参考
背景:
自己是专门从事嵌入式C开发的,因项目需要在手机上写个APP(之前也搞过一个简单的手机APP)。自己专门从事C的自然很多代码是C,该项目中后台软件也是C(需要在多个系统平台上运行),意味着android代码需要调用C代码。首先想到的自然是NDK。
– 第一步自然是搭建平台
自己电脑有eclipse,jdk为r7,算比较新,不要动了
下个NDK(最新为r9),很开心的是了解到自r7之后不再需要cygWin(这是在cygWin快安装好的时候才了解到的,都是因为参考教科书导致的)。
整个环境就是:window xp + eclipse + NDK
(注:罗嗦下,NDK就是个编译器,如果java程序不在android上运行直接在PC上运行,java可直接调用VC编译的dll,那么也就不需要NDK,JNI是一套Java到C/C++的接口)
– 软件安装好了,环境配置下(baidu上有不少这方面资料,根据资料错不了)
– 把所有的C代码拷贝到android项目里的一个文件夹下,通常是jni
(这里关键是要维护好android.mk文件,首先增加减少C文件都需要更改该文件,格式如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := db
LOCAL_SRC_FILES := test1.c\
test2.c
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
(如果要在C中使用Log就必须LOCAL_LDLIBS := -llog)
– 编译后会生成libdb.so库文件
– android中载入该库并可调用其函数
接下来就是主题了(罗嗦了),C的接口中如果要返回中文,会是两个情况:
– 崩溃
– 乱码
简单说下编码(也是折腾后才知道的,如有不对请指正):
android代码:unicode-16
JNI:UTF8
C:通常是GBK
unicode-16和UTF8是同类编码,可以直接通过算法进行转换
GBK是中国特色,GBK到unicode/UTF8只能通过表映射
为了解决问题开始baidu上到处找,方法如下:
– 将文件编码改为UTF-8,修改方式:在eclipse平台上打开代码文件如:test.c,内容剪切,保存,再把内容拷贝回去,保存。然后鼠标放文件上点右键进入属性,有text file ecoding项,选择other中的UTF8编码即可。改后确实可以将中文正常返回到android代码。
问题是不可能将所有C代码换成UTF8,原因有:1、GBK–>UTF8后所有注释荒废 2、C代码中还需要读写外部文件,这个改后是否也要将外部文件转成UTF8?(扯蛋的做法)
以上方法不行,继续找:
– 很多人提到使用iconv,而且有针对window,网上有源代码(头疼),也有编译好的.dll, .lib先下了个,拿到文件后头晕了,怎么将.dll加到android中呢?继续看资料,原来是要把自己的代码在VC上编译成.dll,也就是通过dll嵌套实现iconv的接口应用,但还是这个问题,android上怎么用.dll文件,创建了个普通java app,测试下确实可行。但在android没找到办法 …
– 问题没解决,继续找,终于通过baidu ANSI C GBK 转UTF8找到一个C写的转换函数,文件很大近2W行的代码,里面主要就是映射表,直接将其放进自己的后台软件中参与编译,(除提示文件太大外其他正常,可在起提示中将文件最大行数改下,默认是5000)编译正常,但一用立刻崩溃。测试其崩溃原因发现:
– 如果待转换字符中不带中文不崩溃,如果带中文则崩溃(不是每次都这样)
– 如果待转换字符为中文出来的数据可能为空
看源代码(这还是比较熟悉),发现该文件比较复杂,里面功能比较多,而且有些书写方式也不是自己喜欢的(这些方式在不同平台可能会出异常)。因此开始对其进行裁减,首先把映射表考过来,再将需要的几个接口考过来,把所有感觉不舒服的书写方式改成自己喜欢的方式。(代码中最大一个问题就是映射表使用的是初始化函数的栈内存,该函数退出后该内存命运也就只有上帝知道了,将该表提到函数外使用堆内存)
编译测试通过。
声明:OSCHINA 博客文章版权属于作者,受法律保护。未经作者同意不得转载。