1. 程式人生 > >android使用C/C++呼叫SO庫

android使用C/C++呼叫SO庫

轉載來源:http://biancheng.dnbcw.info/shouji/400358.html

有時候,我們反編譯apk得到一個so庫,如果直接使用這個so庫的話,必須使用原來so庫同樣的package名字,才能用。

這樣人家反編譯你的apk,就知道你侵犯了人家的版權。為了達到混淆的目的,我們可以再寫一個so庫呼叫人家的so庫,即把人家的so庫放到root的某個路徑下,用c/c++語言呼叫這個so庫。比如說,我得到一個APK,反編譯這個APK看到下面的程式碼:
    static {
        try {
            System.loadLibrary("NativeExampleActivity");
        } catch (Throwable t) {
        }
    }
    public native int addFunction(int a, int b);
    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建立一個專案
package so.hello;


import android.app.Activity;
import android.os.Bundle;


public class SoHelloActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    static {
        try {
            System.loadLibrary("soHello");
        } catch (Throwable t) {
        }
    }
    public native int addFunction1(int a, int b);
    public native String getString1(String name);
}


2.在終端進入到專案的路徑soHello/bin/classes,執行命令:

[email protected]:~/workspace/soHello/bin/classes$ javah -jni so.hello.SoHelloActivity
在soHello/bin/classes目錄下會生成一個檔案so_hello_SoHelloActivity.h
</pre><pre name="code" class="java">/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class so_hello_SoHelloActivity */

#ifndef _Included_so_hello_SoHelloActivity
#define _Included_so_hello_SoHelloActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     so_hello_SoHelloActivity
 * Method:    addFunction1
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_so_hello_SoHelloActivity_addFunction1
  (JNIEnv *, jobject, jint, jint);

/*
 * Class:     so_hello_SoHelloActivity
 * Method:    getString1
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_so_hello_SoHelloActivity_getString1
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif



3.寫一個so_hello_SoHelloActivity.cpp檔案
#include "so_hello_SoHelloActivity.h" 
#include <stdlib.h>
#include <fcntl.h>
#include <android/log.h>
#include <stdio.h>  
#include <stdarg.h>  
#include <dlfcn.h> 

void *filehandle = NULL;
jint (*addFunc)(JNIEnv *,jobject,jint,jint) = NULL;
jstring (*getStringFunc)(JNIEnv *, jobject, jstring) = NULL;

JNIEXPORT jint JNICALL Java_so_hello_SoHelloActivity_addFunction1
  (JNIEnv *env, jobject obj, jint a, jint b);
{
	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;
	}
	return mun
}

/*
 * Class:     so_hello_SoHelloActivity
 * Method:    getString1
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_so_hello_SoHelloActivity_getString1
  (JNIEnv *, jobject, jstring name)
{
	jstring mun = 0;
	//事先把libNativeExampleActivity放到root/system/lib/目錄下
	filehandle = dlopen("/system/lib/libNativeExampleActivity.so", RTLD_LAZY);
	if(filehandle)
	{
		getStringFunc = (jstring (*)(JNIEnv *,jobject,jstring))dlsym(filehandle, "Java_org_natives_example_NativeExampleActivity_getString");
		if(getStringFunc)
		{
			mun = getStringFunc(env, obj, name);
		}
		dlclose(filehandle); 
		filehandle = NULL;
	}
	return mun
}


4.編寫Android.mk
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_LDLIBS := -llog
LOCAL_C_INCLUDES += system/core/include/cutils
LOCAL_SHARED_LIBRARIES := \
    libdl \
    libcutils

LOCAL_PRELINK_MODULE := false
LOCAL_MODULE      := libsoHello
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES   := so_hello_SoHelloActivity.cpp
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog

include $(BUILD_SHARED_LIBRARY)
使用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;
}


相關推薦

android使用C/C++呼叫SO

轉載來源:http://biancheng.dnbcw.info/shouji/400358.html 有時候,我們反編譯apk得到一個so庫,如果直接使用這個so庫的話,必須使用原來so庫同樣的package名字,才能用。 這樣人家反編譯你的apk,就知道你侵犯了人家

JNI開發(一) 簡單的C程式碼打包成SO以及專案如何呼叫SO

前段時間開發過程中用到了簡單的JNI使用,當時發現很多網上文章總有這樣那樣的問題,最近趁時間充裕就記錄下來,以供記憶和交流。 JNI環境配置 這裡就不做多講,百度一下,把腳跨過牆就好。 寫

Android呼叫soc語言編寫) Codeblocks+adt-win-x86+ndk-r9c

Android呼叫so庫, so庫是c語言編寫, 在linux 64位系統+ndk(32位)生成 lib*.so (32位) 1. 所需軟體環境: 1)so庫開發環境 作業系統: Redhat Server 6.3  x86_64 編譯軟體:Code::Blocks And

(三)NDK 開發之生成並呼叫 so

1、生成so 庫。 新建一個專案,勾選 Include C++ support.然後一直next。 在配置好NDK 的情況下,系統會直接生成一個呼叫C++ 的 例子,直接執行就可以。 配置NDK:https://blog.csdn.net/lijia1201900857/art

Linux下JNA 呼叫 so

原文:https://blog.csdn.net/withiter/article/details/8077470  博文連結:https://i.cnblogs.com/EditPosts.aspx?opt=1在linux下使用jna呼叫本地方法的時候,需要將C寫成的程式編譯為so檔案1、寫一個簡

Android Studio中so的建立與使用、jar(jar呼叫so)的建立與使用(一)

工程下載https://download.csdn.net/download/cnicfhnui/10422621一、Android Studio 建立so庫,呼叫so庫第一步先下載NDK開發包,下載地址:https://developer.android.google.cn

Android 靜態和動態的呼叫so(JNI)

優點 為什麼我們需要動態載入?因為靜態載入中CPU的資料夾我們可能需要相容的話需要放在不同arm資料夾下,那麼就會導致apk 包體過大,還有安卓Android SDK系統版本導致的差異,所以我們採用動態載入 so 庫檔案的話最主要的好處就是可以減小

C#呼叫DLL的方法

net平臺上,呼叫dll檔案有2種含義1、呼叫託管dll,即你使用。net平臺開發的dll,屬於託管程式碼2、呼叫非託管dll,即傳統的dll,一般是C++,VB,DELPHI等等開發出來的,屬於非託管程式碼。從你的意思中看出來你現在是呼叫託管的dll,方法是 “在

c++呼叫靜態和動態

呼叫靜態庫 第一步把動態庫放到檔案裡 第二部連線上靜態庫 #pragma comment(lib,"靜態庫.lib") 呼叫動態庫 第一步 typedef int( *getMaxNum)(i

AndroidStudio中呼叫So方法

想要呼叫.so檔案,必須先引入.so……是不是有點廢話了。 據說沒有圖片的閱讀很麻煩(完全正確啊)…… 首先 (1) 將AS切換到Project目錄,在main下新建jniLibs,在jniLibs下新建armeabi,把so庫copy進去;  然後,講講呼叫的方法 (

Android 呼叫so全過程

一、前言 Android中有時候為了效率以及平臺開發庫的支援,難免會用到NDK開發,那麼都會產生一個so檔案,通過native方法進行呼叫,開發和呼叫步驟很簡單,這裡就不多說了,本文主要來介紹,我們在使用so的時候總是會出現一些常見的問題,而現在外掛化開發也很普遍了,有時候外掛中也會包含一些s

c++呼叫動態的方法

一、建立動態庫(vs2013)    可以建立一個空的c++專案,寫好庫裡的函式;最後在編譯時,生成動態庫,我這裡隨便寫了個函式 然後右鍵專案名,選擇“屬性”,“常規”,“配置型別”改成“動態庫(.dll)”如圖: 再點選生成即可生成動態庫 二、呼叫動態庫 1、建立一個

linxu下隱式呼叫so

最近,一直在編寫跨平臺的介面庫,庫都編寫成了linux下的so庫檔案,涉及到了對so的呼叫問題,在windows下,有對動態連結庫的兩種方式載入,一是顯示載入,即:手動load庫,二是隱式載入庫,即:只需要標頭檔案和lib檔案,標頭檔案在編譯過程需要,lib檔案在連結過程需

C呼叫libcurl函式 查詢全文搜尋引擎 Elasticsearch

//執行在ubuntu64系統下//curles.c#include <stdio.h>#include <curl/curl.h>#include <string.h>size_t write_data(void *ptr, size_t

如何將自己寫的一段C++程式碼封裝成.so以供其他人呼叫

1.通過自己寫的canbus函式程式碼,先生成一個libcanbus.so連結庫 canbus.cpp程式碼如下: 編譯指令如下: $ g++ -Wall -g -fPIC -c canbus.cpp -o canbus.o $ g++ -

一篇好文之Android 呼叫C程式碼及生成除錯so

不靠譜的朱先生又來了,今天是週五,我又出現了!好了,不為自己多解釋,上週沒發文章,其實我寫了,只是沒有發出來而已……機智ovo。 上週寫的文章是關於GreenDao全面解析,其實當時是想寫一個關於資料庫的系列文章,後來一共就寫了兩篇,SQlite全面解析和GreenDao全面解析。至

java jni呼叫c/c++的so動態連結簡易demo

需求:            工作中需要多個團隊協作開發,而不同團隊提供的程式語言不同,比較常見的是底層互動使用C++或c來實現任務排程,java層實現業務排程或者業務實現,正好有涉及到這方面的應用,就分享一下java使用jni呼叫linux中so檔案的幾個注意事項編寫簡易的

使用JNA呼叫c/c++的so動態函式

       最近專案收到個需求,需要呼叫c寫的函式,給的是so檔案,查閱了資料,so檔案為linux下的動態庫函式檔案,windos下為dll檔案。傳統方案用JNI方式進行連線,大致看了下JNI方式實在麻煩,崩潰中找到JNA,併成功實現了呼叫,特此記錄使用過程。 一、將s

c++呼叫c語言的so動態

1.環境  ubuntu14.04   gcc 4.8.4 g++ 4.8.4 2.庫檔案 1)原始碼 //clTest.c int add(int a, int b) { return a + b; } 2)生成庫檔案 cd到clTest.c所

c++呼叫c++的so動態2

1.環境  ubuntu 14.04  g++ 4.8.4 2.有類的情況 1)庫檔案 a)原始碼 //cppl2.h class cal { public: cal(); virtual ~