android使用C/C++调用SO库

宁可枝头抱香死,何曾吹落北风中。这篇文章主要讲述android使用C/C++调用SO库相关的知识,希望能为你提供帮助。
有时候,我们反编译apk得到一个so库,如果直接使用这个so库的话,必须使用原来so库同样的package名字,才能用。
这样人家反编译你的apk,就知道你侵犯了人家的版权。为了达到混淆的目的,我们可以再写一个so库调用人家的so库,即把人家的so库放到root的某个路径下,用c/c++语言调用这个so库。比如说,我得到一个APK,反编译这个APK看到下面的代码:
 
[html]  view plaincopy    

  1. static  {   
  2.         try  {   
  3.                 System.loadLibrary("NativeExampleActivity");    
  4.         }  catch  (Throwable  t)  {   
  5.         }   
  6. }   
  7. public  native  int  addFunction(int  a,  int  b);    
  8. public  native  String  getString(String  name);    
很明显,这个so库是libNativeExampleActivity.so, 库里面有两个native函数addFunction和getString。
虽然知道了这两个native函数,但是我们还不能直接使用,因为这两个native函数在so库里面的真实函数名不是addFunction和getString,
它在native函数名之前还有包名,所以必须使用nm命令,查看so库里面的函数名。
显示so库函数的命令:
nm -A libNativeExampleActivity.so
或者
nm -D libNativeExampleActivity.so
这样我们看到so库里的主要信息:
java_org_natives_example_NativeExampleActivity_addFunction
Java_org_natives_example_NativeExampleActivity_getString
看到没有,在addFunction函数前面还有包名,这就是为什么直接使用人家的so库的时候,一定要使用原来的package名字!
好了,现在是怎么调用这两个函数了,4个步骤完成。
1.用Eclipse创建一个项目
[html]  view plaincopy    
  1. package  so.hello;    
  2.    
  3. import  android.app.Activity;    
  4. import  android.os.Bundle;    
  5.    
  6. public  class  SoHelloActivity  extends  Activity  {   
  7.         /**  Called  when  the  activity  is  first  created.  */   
  8.         @Override   
  9.         public  void  onCreate(Bundle  savedInstanceState)  {   
  10.                 super.onCreate(savedInstanceState);    
  11.                 setContentView(R.layout.main);    
  12.         }   
  13.         static  {   
  14.                 try  {   
  15.                         System.loadLibrary("soHello");    
  16.                 }  catch  (Throwable  t)  {   
  17.                 }   
  18.         }   
  19.         public  native  int  addFunction1(int  a,  int  b);    
  20.         public  native  String  getString1(String  name);    
  21. }   
2.在终端进入到项目的路径soHello/bin/classes,执行命令:
[email  protected]:~/workspace/soHello/bin/classes$ javah -jni so.hello.SoHelloActivity
在soHello/bin/classes目录下会生成一个文件so_hello_SoHelloActivity.h
 
 
[html]  view plaincopy    
  1. /*  DO  NOT  EDIT  THIS  FILE  -  it  is  machine  generated  */   
  2. #include  < jni.h>    
  3. /*  Header  for  class  so_hello_SoHelloActivity  */   
  4.    
  5. #ifndef  _Included_so_hello_SoHelloActivity   
  6. #define  _Included_so_hello_SoHelloActivity   
  7. #ifdef  __cplusplus   
  8. extern  "C"  {   
  9. #endif   
  10. /*   
  11.   *  Class:          so_hello_SoHelloActivity   
  12.   *  Method:        addFunction1   
  13.   *  Signature:  (II)I   
  14.   */   
  15. JNIEXPORT  jint  JNICALL  Java_so_hello_SoHelloActivity_addFunction1   
  16.     (JNIEnv  *,  jobject,  jint,  jint);    
  17.    
  18. /*   
  19.   *  Class:          so_hello_SoHelloActivity   
  20.   *  Method:        getString1   
  21.   *  Signature:  (Ljava/lang/String; )Ljava/lang/String;    
  22.   */   
  23. JNIEXPORT  jstring  JNICALL  Java_so_hello_SoHelloActivity_getString1   
  24.     (JNIEnv  *,  jobject,  jstring);    
  25.    
  26. #ifdef  __cplusplus   
  27. }   
  28. #endif   
  29. #endif   

3.写一个so_hello_SoHelloActivity.cpp文件
 
 
[html]  view plaincopy    
  1. #include  "so_hello_SoHelloActivity.h"     
  2. #include  < stdlib.h>    
  3. #include  < fcntl.h>    
  4. #include  < android/log.h>    
  5. #include  < stdio.h>        
  6. #include  < stdarg.h>        
  7. #include  < dlfcn.h>      
  8.    
  9. void  *filehandle  =  NULL;    
  10. jint  (*addFunc)(JNIEnv  *,jobject,jint,jint)  =  NULL;    
  11. jstring  (*getStringFunc)(JNIEnv  *,  jobject,  jstring)  =  NULL;    
  12.    
  13. JNIEXPORT  jint  JNICALL  Java_so_hello_SoHelloActivity_addFunction1   
  14.     (JNIEnv  *env,  jobject  obj,  jint  a,  jint  b);    
  15. {   
  16.         jint  mun  =  0;    
  17.         //事先把libNativeExampleActivity放到root/system/lib/目录下   
  18.         filehandle  =  dlopen("/system/lib/libNativeExampleActivity.so",  RTLD_LAZY);    
  19.         if(filehandle)   
  20.         {   
  21.                 addFunc  =  (jint  (*)(JNIEnv  *,jobject,jint,jint))dlsym(filehandle,  "Java_org_natives_example_NativeExampleActivity_addFunction");    
  22.                 if(addFunc)   
  23.                         mun  =  addFunc(env,  obj,  a,  b);    
  24.                 dlclose(filehandle);      
  25.                 filehandle  =  NULL;    
  26.         }   
  27.         return  mun   
  28. }   
  29.    
  30. /*   
  31.   *  Class:          so_hello_SoHelloActivity   
  32.   *  Method:        getString1   
  33.   *  Signature:  (Ljava/lang/String; )Ljava/lang/String;    
  34.   */   
  35. JNIEXPORT  jstring  JNICALL  Java_so_hello_SoHelloActivity_getString1   
  36.     (JNIEnv  *,  jobject,  jstring  name)   
  37. {   
  38.         jstring  mun  =  0;    
  39.         //事先把libNativeExampleActivity放到root/system/lib/目录下   
  40.         filehandle  =  dlopen("/system/lib/libNativeExampleActivity.so",  RTLD_LAZY);    
  41.         if(filehandle)   
  42.         {   
  43.                 getStringFunc  =  (jstring  (*)(JNIEnv  *,jobject,jstring))dlsym(filehandle,  "Java_org_natives_example_NativeExampleActivity_getString");    
  44.                 if(getStringFunc)   
  45.                 {   
  46.                         mun  =  getStringFunc(env,  obj,  name);    
  47.                 }   
  48.                 dlclose(filehandle);      
  49.                 filehandle  =  NULL;    
  50.         }   
  51.         return  mun   
  52. }   

4.编写Android.mk
 
 
[html]  view plaincopy    
  1. LOCAL_PATH  :=  $(call  my-dir)   
  2.    
  3. include  $(CLEAR_VARS)   
  4.    
  5. LOCAL_LDLIBS  :=  -llog   
  6. LOCAL_C_INCLUDES  +=  system/core/include/cutils   
  7. LOCAL_SHARED_LIBRARIES  :=  \   
  8.         libdl  \   
  9.         libcutils   
  10.    
  11. LOCAL_PRELINK_MODULE  :=  false   
  12. LOCAL_MODULE            :=  libsoHello   
  13. LOCAL_MODULE_TAGS  :=  optional   
  14. LOCAL_SRC_FILES      :=  so_hello_SoHelloActivity.cpp   
  15. LOCAL_LDLIBS  :=  -L$(SYSROOT)/usr/lib  -llog   
  16.    
  17. include  $(BUILD_SHARED_LIBRARY)   
【android使用C/C++调用SO库】
使用mm命令编译so_hello_SoHelloActivity.cpp,便可以生成libsoHello.so库。
然后这个so库就可以用啦!

综述:
这里主要使用了dlopen、dlsym、dlclose三个函数来加载so库:
void *filehandle = NULL;
jint (*addFunc)(JNIEnv *,jobject,jint,jint) = NULL;
jint mun = 0
//事先把libNativeExampleActivity放到root/system/lib/目录下
filehandle = dlopen("/system/lib/libNativeExampleActivity.so", RTLD_LAZY);
if(filehandle)
{
      addFunc = (jint (*)(JNIEnv *,jobject,jint,jint))dlsym(filehandle, "Java_org_natives_example_NativeExampleActivity_addFunction");
      if(addFunc)
            mun = addFunc(env, obj, a, b);
      dlclose(filehandle);  
      filehandle = NULL;
}




































    推荐阅读