2021-05-12 14:32:11
android ndk 動態庫
android ndk開發經常遇到了動態庫的問題,本文主要介紹:
① 動態連結庫的生成;
② 在Java和C混合程式設計的情況下如何呼叫第三方動態連結庫;
③ 使用dlopen程式執行時直接呼叫;
④ 純c的方式開發呼叫;
本文重點推薦②和④,第③中太麻煩每個函數都需要dlsym呼叫一次;
程式碼的百度雲連結: http://pan.baidu.com/s/1dD3qkQ9 密碼:c5s3
1
android ndk下面生成動態庫so檔案的方法很多,但是這裡只提供一種方法,更多的生成方法可以看,「ndk 編譯靜態庫」:http://jingyan.baidu.com/article/63f236280b90690208ab3d12.html2
fkAdd.c 的內容如下:#include <jni.h>int fkAdd(int nX, int nY){? ? ? returnnX + nY;}3
Android.mk 的內容如下:LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE:= fkAddLOCAL_SRC_FILES:= fkAdd.cinclude $(BUILD_SHRRED_LIBRARY)4
1、開啟 eclipse
2、點選 檔案
3、點選 新建
4、點選 other...
5
1、展開 Android 選項;
2、選擇 Android Project from Existing Code;
3、點選 Next
6
1、輸入 Root Director;
2、取消 tests;
3、選中 Copy projects into workspace;
4、點選 Finish;
7
1、右鍵工程;
2、選擇 Android Tools;
3、Add Native Support...;
8
點選 Finish
9
修改android sdk 版本為 4.0.3;關於如何修改 android sdk 版本:http://jingyan.baidu.com/article/c910274bfdd000cd371d2d4b.html10
修改 Min SDK version:15
修改 Target SDK version:19
11
在jni目錄下面新建檔案fkAdd.c 的內容如下:int fkAdd(int nX, int nY){? ? ? returnnX + nY;}12
臨時修改 Android.mk 檔案內容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
#LOCAL_MODULE := hello-jni
#LOCAL_SRC_FILES := hello-jni.c
LOCAL_MODULE := fkaddso
LOCAL_SRC_FILES := fkAdd.c
include $(BUILD_SHARED_LIBRARY)
13
使用快捷鍵Ctrl+B編譯後可以在libs目錄下面看到生成的一些列的
libfkaddso.so檔案,如下圖所示
1
1、將libs複製一份到jni目錄下面,刪掉其中不相關的檔案
2、刪掉檔案 jni/fkadd.c 檔案
3、將 Android.mk 檔案還原成最開始的樣子;
2
修改 hello-jni.c 中的部分程式碼,如下:
char szMsg[1024] = {0};
int nSum = fkAdd(100, 10);
sprintf (szMsg, "Hello from JNI ! Compiled with ABI " ABI ". %d ", nSum);
return (*env)->NewStringUTF(env, szMsg);
3
修改 Android.mk 檔案:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := fkaddso
LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libfkaddso.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
LOCAL_SHARED_LIBRARIES := fkaddso
include $(BUILD_SHARED_LIBRARY)
4
修改 HelloJni.java 在其中增加一行:
System.loadLibrary("fkaddso");
5
執行工程看效果:
1
重複「生成動態庫」中的過程1到10,2
把需要呼叫so檔案的目錄libs拷貝到jni目錄下面,並修改 Android.mk 檔案的內容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := fkaddso
LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libfkaddso.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
include $(BUILD_SHARED_LIBRARY)
3
修改 hello-jni.c 的內容如下:
char*szSo = "/data/data/com.example.hellojni/lib/libfkaddso.so";
void* fkAddSo = dlopen(szSo, RTLD_LAZY);
int (*fpAdd)(int,int) = (int (*)(int,int))dlsym(fkAddSo, "fkAdd");
char szMsg[1024] = {0};
int nSum = fpAdd(100, 200);
dlclose(fkAddSo);
sprintf (szMsg, "%s %d", szSo, nSum);
return (*env)->NewStringUTF(env, szMsg);
4
關於如何獲取 so在手機中的路徑,可以通過在控制台下輸入 adb shell 後,
在手機上查詢:
5
編譯後執行效果:
6
方便他人亦是方便自己,如果覺得還行就點下下邊的投票吧,這樣可以幫助其他人更快的找到解決問題的方法;有疑問的也可留言哦, 謝謝!
1
此方法需要感謝ndk吧的吧友提供哦,本人只是負責將其進行了整理,歸納後發帖,謝謝,原始地址:http://tieba.baidu.com/p/32475300802
根據「生成動態庫」中的過程1到10,新建一個純c的ndk程式:
「D:Androidandroid-ndk-r10samplesnative-activity"
3
把會用的so檔案的目錄libs拷貝到 jni目錄下面
4
修改 Android.mk 檔案,內容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := fkAdd
LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libfkAdd.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := main
LOCAL_SRC_FILES := main.c
LOCAL_LDLIBS := -llog -landroid -lEGL -lGLESv1_CM
LOCAL_STATIC_LIBRARIES := android_native_app_glue
LOCAL_SHARED_LIBRARIES := fkAdd
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := native-activity
LOCAL_SRC_FILES := NativeActivity.c
LOCAL_LDLIBS := -llog -landroid
LOCAL_STATIC_LIBRARIES := android_native_app_glue
include $(BUILD_SHARED_LIBRARY)
$(call import-module,android/native_app_glue)
5
增加 NativeActivity.c 檔案,新增內容如下:
#include <jni.h>
#include <errno.h>
#include <dlfcn.h>
#include <android_native_app_glue.h>
void android_main(struct android_app* state) {
// Make sure glue isn't stripped.
app_dummy();
void* soAdd = dlopen("/data/data/com.example.native_activity/
lib/libfkAdd.so",RTLD_NOW);
void* soMain = dlopen("/data/data/com.example.native_activity/
lib/libmain.so",RTLD_NOW);
void (*fp_android_main)(struct android_app*) =
(void (*)(struct android_app*))dlsym(soMain,"android_main");
fp_android_main(state);
dlclose(soMain);
dlclose(soAdd);
}
6
在 main.c 檔案中新增一行,方便測試:
__android_log_print(ANDROID_LOG_DEBUG, "fuke", "engine_handle_input 100 + 200 = [%d] ", fkAdd(100, 200));
7
編譯執行,點選手機螢幕後,觀察logcat 效果如下:
相關文章