本文共 8799 字,大约阅读时间需要 29 分钟。
使用Android NDK同时编译libxml2和libiconv库
首先做好准备工作按照如下创建好目录并准备好libiconv和libxml2的压缩文件 (我这里使用的版本为:libiconv-1.14.tar.gz libxml2-git-snapshot.tar.gz【libxml2-2.8.0】) 创建目录如下 buildlibxml2(root) jni->Android.mk (root-child) jni->main.c (root-child) libiconv (root-child) libxml2 (root-child) Android.mk文件如下: LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := main LOCAL_SRC_FILES := main.c LOCAL_C_INCLUDES := \ $(LOCAL_PATH)/libxml2/include \ $(LOCAL_PATH)/libxml2/include/libxml \ $(LOCAL_PATH)/libiconv/include \ $(LOCAL_PATH)/libiconv \ $(LOCAL_PATH)/libiconv/libcharset \ $(LOCAL_PATH)/libiconv/lib \ $(LOCAL_PATH)/libiconv/libcharset/include LOCAL_SHARED_LIBRARIES := libiconv libxml2 include $(BUILD_EXECUTABLE) include $(call all-makefiles-under,$(LOCAL_PATH)) main.c 文件如下 #include <stdio.h> #include <stdlib.h> #include "libxml2/include/libxml/parser.h" #include "libxml2/include/libxml/tree.h"int main (int argc, char **argv)
{ xmlDocPtr pdoc = NULL; xmlNodePtr proot_node = NULL,pnode = NULL,pnode1 = NULL; pdoc = xmlNewDoc (BAD_CAST "1.0"); proot_node = xmlNewNode (NULL, BAD_CAST "root node"); xmlNewProp (proot_node, BAD_CAST "version", BAD_CAST "1.0"); xmlDocSetRootElement (pdoc, proot_node); pnode = xmlNewNode (NULL, BAD_CAST "child node 1"); xmlNewChild (pnode, NULL, BAD_CAST "child child node 1", BAD_CAST "info"); xmlAddChild (proot_node, pnode); pnode1 = xmlNewNode (NULL, BAD_CAST "child child node 1"); xmlAddChild (pnode, pnode1); xmlAddChild (pnode1,xmlNewText (BAD_CAST "this will lower node, child child child node 1")); xmlNewTextChild (proot_node, NULL, BAD_CAST "child node 2", BAD_CAST "child node 2 info"); xmlNewTextChild (proot_node, NULL, BAD_CAST "child node 3", BAD_CAST "child node info 3"); xmlSaveFormatFileEnc (argc > 1 ? argv[1]:"-", pdoc, "UTF-8", 1); xmlFreeDoc (pdoc); xmlCleanupParser (); xmlMemoryDump (); return 0; } 将libiconv库和libxml2用tar xvvzf 命令解压 进入终端 进入libiconv目录 ./configure --build=x86_64-pc-linux-gnu --host=arm-linux-eabi 进入libxml2目录 ./configure (用上面的命令卡到某个步骤因此用这个) 在libiconv和libxml2文件夹里面添加Android.mk文件文件分别为 libiconv Android.mk: LOCAL_PATH:= $(call my-dir) #libiconv.so include $(CLEAR_VARS) LOCAL_MODULE := libiconv LOCAL_CFLAGS := \ -Wno-multichar \ -DANDROID \ -DLIBDIR="c" \ -DBUILDING_LIBICONV \ -DIN_LIBRARY LOCAL_SRC_FILES := \ libcharset/lib/localcharset.c \ lib/iconv.c \ lib/relocatable.c LOCAL_C_INCLUDES += \ $(LOCAL_PATH)/include \ $(LOCAL_PATH)/libcharset \ $(LOCAL_PATH)/lib \ $(LOCAL_PATH)/libcharset/include \ $(LOCAL_PATH)/srclib include $(BUILD_SHARED_LIBRARY) libxml2 Android.mk: LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := \ c14n.c catalog.c chvalid.c debugXML.c dict.c DOCBparser.c \ encoding.c entities.c error.c globals.c hash.c HTMLparser.c \ HTMLtree.c legacy.c list.c nanoftp.c nanohttp.c parser.c \ parserInternals.c pattern.c relaxng.c SAX.c SAX2.c \ threads.c tree.c trionan.c triostr.c uri.c valid.c\ xinclude.c xlink.c xmlIO.c xmlmemory.c xmlmodule.c \ xmlreader.c xmlregexp.c xmlsave.c xmlschemas.c xmlschemastypes.c xmlstring.c \ xmlunicode.c xmlwriter.c xpath.c xpointer.c LOCAL_C_INCLUDES := \ $(LOCAL_PATH)/include \ $(LOCAL_PATH)/include/libxml \ $(LOCAL_PATH)/../libiconv/include \ $(LOCAL_PATH)/../libiconv \ $(LOCAL_PATH)/../libiconv/libcharset \ $(LOCAL_PATH)/../libiconv/lib \ $(LOCAL_PATH)/../libiconv/libcharset/include LOCAL_MODULE:=libxml2 LOCAL_SHARED_LIBRARIES :=libiconv include $(BUILD_SHARED_LIBRARY) 打开终端进入buildlibxml2目录 进行ndk-build 报错 langinfo.h No such file or directiory 查找原因查看文件 \buildlibxml2\jni\libiconv\libcharset\lib\localcharset.c # if HAVE_LANGINFO_CODESET # include <langinfo.h> # else # if 0 /* see comment below */ # include <locale.h> # endif # endif 解决方法将\buildlibxml2\jni\libiconv\libcharset\config.h里面 将HAVE_LANGINFO_CODESET定义改成 0 #define HAVE_LANGINFO_CODESET 0 报错 'c'undeclared identitfier 查找原因查看文件 \buildlibxml2\jni\libiconv\libcharset\lib\localcharset.c 搜索int c 将int c的定义移到get_charset_aliases函数的开头报错 ansidecl.h No such file or directiory
查找原因查看文件\buildlibxml2\jni\libxml2\include\libxml\xmlversion.h #ifdef HAVE_ANSIDECL_H #include <ansidecl.h> #endif 解决方法打开文件\buildlibxml2\jni\libxml2\config.h 将define HAVE_ANSIDECL_H注释 //#define HAVE_ANSIDECL_H 1 报各类的如gzdopen gzopen 未定义的问题 将\buildlibxml2\jni\libxml2\config.h HAVE_LIBZ 和HAVE_ZLIB_H //#define HAVE_LIBZ 1 //#define HAVE_ZLIB_H 1 注释 报错 rand_r未定义 查找原因查看文件\buildlibxml2\jni\libxml2\dict.c #ifdef HAVE_RAND_R rand_seed = time(NULL); rand_r(& rand_seed); #else srand(time(NULL)); #endif #ifdef HAVE_RAND_R ret = rand_r(& rand_seed); #else ret = rand(); #endif 解决方法打开文件\buildlibxml2\jni\libxml2\config.h 将HAVE_RAND_R 定义注释 //#define HAVE_RAND_R 1重新ndk-build完成成功编译
编译这2个库我只遇到以上的一些问题。还是很幸运。编译好了!准备去用一下看可以用不痛苦的是我编译的可执行文件用cygwin在不能直接用- -#哎!悲哀 直接是说cannot execute binary file 然后我就在linux下用也是一样。。。不能执行二进制文件 然后我push到android模拟器上看能不能用./main运行..悲催permission denied 没有权限 你叫我情何以堪....是不是要root模拟器.... 试了一下一个命令 adb remount adb shell mount -o remount,rw -t yaffs2 /dev/block/mtdblock3 /system cd /system/bin cat sh > su chmod 4755 su su 发现不行 算了 还是好好的改JNI连接测试了。 哈哈哈!! 主activity: package build.libxml2; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.widget.TextView; public class testActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //setContentView(R.layout.main); TextView tv=new TextView(this); tv.setText("开始程序运行了!"); Log.v("1", "程序开始了!"); setContentView(tv); tv.setText("开始运行xmltest()了!"); Log.v("1", "开始运行xmltest()了"); natives.xmltest(); } } natives.class package build.libxml2; import android.util.Log; public class natives { static { Log.v("loadlibrary","start load iconv"); System.loadLibrary("iconv"); Log.v("loadlibrary","succse load iconv"); Log.v("loadlibrary","start load xml2"); System.loadLibrary("xml2"); Log.v("loadlibrary","succse load xml2"); Log.v("loadlibrary","start load main"); System.loadLibrary("main"); Log.v("loadlibrary","succse load main"); } public static native void xmltest(); } 将main.c文件修改 #include <stdio.h> #include <stdlib.h> #include "libxml2/include/libxml/parser.h" #include "libxml2/include/libxml/tree.h" #include <jni.h> #include <android/log.h> JNIEXPORT void JNICALL Java_build_libxml2_natives_xmltest (JNIEnv *env, jclass jc) { int i; __android_log_print(ANDROID_LOG_INFO,"FILE_OPT","run to testmain"); i=testmain(); __android_log_print(ANDROID_LOG_INFO,"FILE_OPT","fun return %d",i); } //int main (int argc, char **argv) int testmain() { char *szDocName="/mnt/sdcard/yy.xml"; FILE *fp; fp=fopen(szDocName,"a+"); if(fp == NULL) { fclose(fp); return 0; } __android_log_print(ANDROID_LOG_INFO,"FILE_OPT","file create"); xmlDocPtr pdoc = NULL; xmlNodePtr proot_node = NULL,pnode = NULL,pnode1 = NULL; pdoc = xmlNewDoc (BAD_CAST "1.0"); proot_node = xmlNewNode (NULL, BAD_CAST "root node"); xmlNewProp (proot_node, BAD_CAST "version", BAD_CAST "1.0"); xmlDocSetRootElement (pdoc, proot_node); pnode = xmlNewNode (NULL, BAD_CAST "child node 1"); xmlNewChild (pnode, NULL, BAD_CAST "child child node 1", BAD_CAST "info"); xmlAddChild (proot_node, pnode); pnode1 = xmlNewNode (NULL, BAD_CAST "child child node 1"); xmlAddChild (pnode, pnode1); xmlAddChild (pnode1,xmlNewText (BAD_CAST "this will lower node, child child child node 1")); xmlNewTextChild (proot_node, NULL, BAD_CAST "child node 2", BAD_CAST "child node 2 info"); xmlNewTextChild (proot_node, NULL, BAD_CAST "child node 3", BAD_CAST "child node info 3"); //xmlSaveFormatFileEnc (argc > 1 ? argv[1]:"-", pdoc, "UTF-8", 1); xmlSaveFormatFileEnc(szDocName,pdoc, "UTF-8", 1); xmlFreeDoc (pdoc); xmlCleanupParser (); xmlMemoryDump (); return 0; }将\buildlibxml2\jni\Android.mk文件修改
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := main LOCAL_SRC_FILES := main.c LOCAL_C_INCLUDES := \ $(LOCAL_PATH)/libxml2/include \ $(LOCAL_PATH)/libxml2/include/libxml \ $(LOCAL_PATH)/libiconv/include \ $(LOCAL_PATH)/libiconv \ $(LOCAL_PATH)/libiconv/libcharset \ $(LOCAL_PATH)/libiconv/lib \ $(LOCAL_PATH)/libiconv/libcharset/include LOCAL_SHARED_LIBRARIES := libiconv libxml2 LOCAL_LDLIBS := -llog include $(BUILD_SHARED_LIBRARY) include $(call all-makefiles-under,$(LOCAL_PATH))进入终端进入目录buildlibxml2 ndk-build
成功生成 在AndroidManifest.xml添加文件访问权限 运行程序。 用adb pull 命令 将/mnt/sdcard/yy.xml拷出来 用notepad查看 <?xml version="1.0" encoding="UTF-8"?> <root node version="1.0"> <child node 1> <child child node 1>info</child child node 1> <child child node 1>this will lower node, child child child node 1</child child node 1> </child node 1> <child node 2>child node 2 info</child node 2> <child node 3>child node info 3</child node 3> </root node> 测试的例子是在网上广为流传的借用然后改写了。具体链接记不起了! 移植这个库参考了一些其他的博客知识但大多是自己撰写和整编。 成功!!!!测试成功至此libxml2和libiconv成功移植到android转载地址:http://xtldi.baihongyu.com/