2014年3月15日土曜日

cocos2dxでlibiconvを利用する方法(iOS,Android版)

さて、ほんとうにこのブログにたまたま足を踏み入れた方が
気になっているかもしれない上記をお話します。

まずはiOS版から
これは簡単です。

general からframewarkで+を選択、検索ワード「libiconv」と検索すると該当のファイルがでるので、追加すればOK!

class上ではincludeして読み込みします
+//これはiconvを利用するためのヘッダ(htmlをiOSで読み取るutf8に変換するため)
+#include <iconv.h>//ちゃんとiOS側のgeneralにも追加して

そして該当ソースとしてはこんな感じ

filepathとfilepath2がありますが、これはコンバート前、後のファイルの場所を指定しています。

+    iconv_t icd;
+    FILE *fp_src, *fp_dst;
+    char s_src[S_SIZE], s_dst[S_SIZE];
+    char *p_src, *p_dst;
+    size_t n_src, n_dst;
+    
+    icd = iconv_open("UTF-8", "EUC-JP");
+    fp_src = fopen(filePath.c_str(), "r");
+    fp_dst = fopen(filePath2.c_str(), "w");
+    
+    while(true){
+        fgets(s_src, S_SIZE, fp_src);
+        if (feof(fp_src))
+            break;
+        p_src = s_src;
+        p_dst = s_dst;
+        n_src = strlen(s_src);
+        n_dst = S_SIZE-1;
+        while(0 < n_src){
+            iconv(icd, &p_src, &n_src, &p_dst, &n_dst);
+        }
+        *p_dst = '\0';
+        fputs(s_dst, fp_dst);
+    }
+    
+    fclose(fp_dst);
+    fclose(fp_src);
+    iconv_close(icd);

これで問題なく、ファイルのコンバートができました。

そして次はAndroid版です。
これがなかなか初心者にとってはつらかった点くせ者でした。

まずはlibiconv-1.14をDLしてきます。

そして私は以下ディレクトリを作成してぶちこみました

external/libiconv2


そしてプロジェクトのモジュールとして利用したいので、
以下のAndroid.mkファイルを作成
external/libiconv2/Android.mk
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+#libiconv.so
+LOCAL_MODULE := iconv_static
+
+LOCAL_MODULE_FILENAME := libiconv
+
+LOCAL_CFLAGS := \
+  -Wno-multichar \
+  -DANDROID \
+  -DLIBDIR="c" \
+  -DBUILDING_LIBICONV \
+  -DIN_LIBRARY
+
+LOCAL_SRC_FILES := \
+  libiconv-1.14/libcharset/lib/localcharset.c \
+  libiconv-1.14/lib/iconv.c \
+  libiconv-1.14/lib/relocatable.c
+
+LOCAL_C_INCLUDES += \
+  $(LOCAL_PATH)/libiconv-1.14/include \
+  $(LOCAL_PATH)/libiconv-1.14/libcharset \
+  $(LOCAL_PATH)/libiconv-1.14/lib \
+  $(LOCAL_PATH)/libiconv-1.14/libcharset/include \
+  $(LOCAL_PATH)/libiconv-1.14/srclib
+ 
+LOCAL_EXPORT_C_INCLUDES       := $(LOCAL_PATH)/libiconv-1.14/include
+include $(BUILD_STATIC_LIBRARY)

そして該当プロジェクトのAndroid.mkファイルも修正しないといけません。
上記のlibiconvを読み込む必要があるためです

proj.android/jni/Android.mk
 LOCAL_WHOLE_STATIC_LIBRARIES += cocosdenshion_static
 LOCAL_WHOLE_STATIC_LIBRARIES += box2d_static
 LOCAL_WHOLE_STATIC_LIBRARIES += chipmunk_static
+LOCAL_WHOLE_STATIC_LIBRARIES += iconv_static 
 
 include $(BUILD_SHARED_LIBRARY)
 
 $(call import-module,cocos2dx)
 $(call import-module,CocosDenshion/android)
 $(call import-module,extensions)
 $(call import-module,external/Box2D)
 $(call import-module,external/chipmunk)
+$(call import-module,external/libiconv2)

こんな感じで、

そして該当classにて以下のようにincludeさせることで利用可能となりました
+#include <../../external/libiconv2/libiconv-1.14/include/iconv.h>

実装のソースはAndroidでは以下のように少し修正してます

     iconv_t icd;
     FILE *fp_src, *fp_dst;
     char s_src[S_SIZE], s_dst[S_SIZE];
-    char const *p_src;
+    char *p_src;
     char *p_dst;
     size_t n_src, n_dst;
     
     icd = iconv_open("UTF-8", "EUC-JP");
     fp_src = fopen(filePath.c_str(), "r");
     fp_dst = fopen(filePath2.c_str(), "w");
     
     while(true){
         fgets(s_src, S_SIZE, fp_src);
         if (feof(fp_src))
             break;
         p_src = s_src;
         p_dst = s_dst;

ちょっとライブラリにより、const を使っているもの、使っていないものがあるようです

これで問題なくコンパイルは通過したのですが、さらなる問題が、、、

実は上記のclassを単独の別クラスにして、他のアプリでも流用が簡単にしようと思ったのですが、iOSだとその状態でも問題なく動作可能。

しかしAndroidではコンパイルは通過するものの、ネイティブ側で以下のエラーが発生

logcatの情報です

03-03 16:48:45.170: I/dalvikvm(1046): Wrote stack traces to '/data/anr/traces.txt'
03-03 16:48:45.211: I/DEBUG(33): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
03-03 16:48:45.211: I/DEBUG(33): Build fingerprint: 'generic/sdk/generic:4.0.4/MR1/302030:eng/test-keys'
03-03 16:48:45.211: I/DEBUG(33): pid: 1046, tid: 1046  >>> com.zawazawa.hotspring <<<
03-03 16:48:45.211: I/DEBUG(33): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr deadbaad
03-03 16:48:45.221: I/DEBUG(33):  r0 deadbaad  r1 00000001  r2 40000000  r3 00000000
03-03 16:48:45.221: I/DEBUG(33):  r4 00000000  r5 00000027  r6 00000001  r7 001a0c90
03-03 16:48:45.221: I/DEBUG(33):  r8 b0012fa8  r9 46e5a000  10 00562000  fp be8b026c
03-03 16:48:45.221: I/DEBUG(33):  ip ffffffff  sp be8b0228  lr 4001f161  pc 4001b8c0  cpsr 60000030
03-03 16:48:45.221: I/DEBUG(33):  d0  3f8000003f800000  d1  3ff0000043200000
03-03 16:48:45.221: I/DEBUG(33):  d2  437e8000000000fe  d3  000000003f000000
03-03 16:48:45.221: I/DEBUG(33):  d4  000001fd00000000  d5  3fe999999999999a
03-03 16:48:45.221: I/DEBUG(33):  d6  3fe8000000000000  d7  000000a000000000
03-03 16:48:45.231: I/DEBUG(33):  d8  0000000000000000  d9  0000000000000000
03-03 16:48:45.231: I/DEBUG(33):  d10 0000000000000000  d11 0000000000000000
03-03 16:48:45.231: I/DEBUG(33):  d12 0000000000000000  d13 0000000000000000
03-03 16:48:45.231: I/DEBUG(33):  d14 0000000000000000  d15 0000000000000000
03-03 16:48:45.231: I/DEBUG(33):  scr 60000012
03-03 16:48:45.641: I/Process(78): Sending signal. PID: 1046 SIG: 3
03-03 16:48:45.641: I/dalvikvm(1046): threadid=3: reacting to signal 3
03-03 16:48:45.691: I/dalvikvm(1046): Wrote stack traces to '/data/anr/traces.txt'
03-03 16:48:45.891: I/DEBUG(33):          #00  pc 000178c0  /system/lib/libc.so
03-03 16:48:45.891: I/DEBUG(33):          #01  lr 4001f161  /system/lib/libc.so
03-03 16:48:45.901: I/DEBUG(33): code around pc:
03-03 16:48:45.901: I/DEBUG(33): 4001b8a0 4623b15c 2c006824 e026d1fb b12368db  \.#F$h.,..&..h#.
03-03 16:48:45.901: I/DEBUG(33): 4001b8b0 21014a17 6011447a 48124798 24002527  .J.!zD.`.G.H'%.$
03-03 16:48:45.901: I/DEBUG(33): 4001b8c0 f7f47005 2106ee50 eeecf7f5 460aa901  .p..P..!.......F
03-03 16:48:45.901: I/DEBUG(33): 4001b8d0 f04f2006 94015380 94029303 eaa8f7f5  . O..S..........
03-03 16:48:45.901: I/DEBUG(33): 4001b8e0 4622a905 f7f52002 f7f4eab2 2106ee3c  .."F. ......<..!
03-03 16:48:45.901: I/DEBUG(33): code around lr:
03-03 16:48:45.911: I/DEBUG(33): 4001f140 41f0e92d 46804c0c 447c2600 68a56824  -..A.L.F.&|D$h.h
03-03 16:48:45.911: I/DEBUG(33): 4001f150 e0076867 300cf9b5 dd022b00 47c04628  gh.....0.+..(F.G
03-03 16:48:45.911: I/DEBUG(33): 4001f160 35544306 37fff117 6824d5f4 d1ee2c00  .CT5...7..$h.,..
03-03 16:48:45.911: I/DEBUG(33): 4001f170 e8bd4630 bf0081f0 0002839a 41f0e92d  0F..........-..A
03-03 16:48:45.921: I/DEBUG(33): 4001f180 fb01b086 9004f602 461f4815 4615460c  .........H.F.F.F
03-03 16:48:45.921: I/DEBUG(33): memory map around addr deadbaad:
03-03 16:48:45.921: I/DEBUG(33): be89c000-be8b1000 [stack]
03-03 16:48:45.921: I/DEBUG(33): (no map for address)
03-03 16:48:45.921: I/DEBUG(33): (no map above)
03-03 16:48:45.921: I/DEBUG(33): stack:
03-03 16:48:45.921: I/DEBUG(33):     be8b01e8  00143b70  [heap]
03-03 16:48:45.931: I/DEBUG(33):     be8b01ec  4004c35c  
03-03 16:48:45.931: I/DEBUG(33):     be8b01f0  400476b0  /system/lib/libc.so
03-03 16:48:45.931: I/DEBUG(33):     be8b01f4  001a0c90  [heap]
03-03 16:48:45.931: I/DEBUG(33):     be8b01f8  4004770c  /system/lib/libc.so
03-03 16:48:45.931: I/DEBUG(33):     be8b01fc  4004c85c  
03-03 16:48:45.931: I/DEBUG(33):     be8b0200  00000000  
03-03 16:48:45.931: I/DEBUG(33):     be8b0204  4001f161  /system/lib/libc.so
03-03 16:48:45.942: I/DEBUG(33):     be8b0208  00000000  
03-03 16:48:45.942: I/DEBUG(33):     be8b020c  be8b023c  [stack]
03-03 16:48:45.951: I/DEBUG(33):     be8b0210  00000001  
03-03 16:48:45.951: I/DEBUG(33):     be8b0214  001a0c90  [heap]
03-03 16:48:45.951: I/DEBUG(33):     be8b0218  b0012fa8  
03-03 16:48:45.951: I/DEBUG(33):     be8b021c  4001e2cd  /system/lib/libc.so
03-03 16:48:45.951: I/DEBUG(33):     be8b0220  df0027ad  
03-03 16:48:45.951: I/DEBUG(33):     be8b0224  00000000  
03-03 16:48:45.961: I/DEBUG(33): #00 be8b0228  400476b0  /system/lib/libc.so
03-03 16:48:45.961: I/DEBUG(33):     be8b022c  0000000a  
03-03 16:48:45.961: I/DEBUG(33):     be8b0230  00000001  
03-03 16:48:45.961: I/DEBUG(33):     be8b0234  4001f6f1  /system/lib/libc.so
03-03 16:48:45.971: I/DEBUG(33):     be8b0238  40047608  /system/lib/libc.so
03-03 16:48:45.971: I/DEBUG(33):     be8b023c  fffffbdf  
03-03 16:48:45.971: I/DEBUG(33):     be8b0240  00000001  
03-03 16:48:45.981: I/DEBUG(33):     be8b0244  40047608  /system/lib/libc.so
03-03 16:48:45.981: I/DEBUG(33):     be8b0248  001eb23c  [heap]
03-03 16:48:45.981: I/DEBUG(33):     be8b024c  46cb3f18  /data/data/com.zawazawa.hotspring/lib/libcocos2dcpp.so
03-03 16:48:45.981: I/DEBUG(33):     be8b0250  0019ceb0  [heap]
03-03 16:48:45.981: I/DEBUG(33):     be8b0254  00000000  
03-03 16:48:45.981: I/DEBUG(33):     be8b0258  0019ceb0  [heap]
03-03 16:48:45.981: I/DEBUG(33):     be8b025c  46cb3e00  /data/data/com.zawazawa.hotspring/lib/libcocos2dcpp.so
03-03 16:48:45.981: I/DEBUG(33):     be8b0260  46cafaf0  /data/data/com.zawazawa.hotspring/lib/libcocos2dcpp.so
03-03 16:48:45.981: I/DEBUG(33):     be8b0264  ffffffff  
03-03 16:48:45.981: I/DEBUG(33):     be8b0268  be8b0274  [stack]
03-03 16:48:45.981: I/DEBUG(33):     be8b026c  46cafac4  /data/data/com.zawazawa.hotspring/lib/libcocos2dcpp.so

こりゃあcrash dumpを以下コマンドでみなきゃあと思ったら、
さらにlibc.soしかログにはでてない。。。

もう謎過ぎたので、ライブラリを一つ一つ消して、追加して、
動作確認しました。

そして迷ったはてに、libiconv利用してファイルの文字コードをコンバートするものを単独別クラス化していたものを、コンバートしたものを表示するクラスと同じところに、
メンバ関数の一つとして追加したら、なぜかネイティブ側でも落ちなくなりましたよ。。。そうとう謎です。

もし原因がわかる方いらっしゃいましたら、ご指摘頂けますと嬉しいです。

androidは不慣れでしたが、crashdumpして、ログにもlibc.soで落ちたことしかわからない様だったら、「一つ一つのライブラリで動作試してみて」
さらにどうしてもだめなら、「全て一緒のクラス内で書いてみる」

学んだことでした。

うーん、開発は奥が深い。。。

0 件のコメント:

コメントを投稿