用ndk环境编译android可用的so库

需求:由于算法人员已经用c++写好了接口,现在要迁移到Android上来,不可能让算法的代码在重新在androidstudio上在重新编写一遍,所以只能把现有的代码封装成android可调用的so库,然后利用JNI在封装成android可使用的接口

首先第一步我们来讲:如何使用ndk环境编译cpp源文件供Android调用

说明:Android上所用的so库必须在NDK环境下编译的才可以,我之前一直使用的是纯linux编译的do库,调用的时候一直报平台不兼容的错,后来才知道必须使用NDK环境编译的才可以,希望能帮助需要的人少走一些弯路,下面开始正经的了~

1)下载Android NDK,下载地址为:https://developer.android.google.cn/ndk/downloads/index.html ,目前最高的版本为android-ndk-r14b

2)将下载好的NDK随便解压缩到一个目录下,我的目录为:D:\updatendk\android-ndk-r14b

3)创建要编译的JNI目录,比如:D:\NDK-Build\jni,并将要编译的C++代码放入sourceCode文件夹下,比如:D:\NDK-Build\jni\sourceCode

4)在jni目录下创建android.mk和Application.mk文件

5)将build_native.bat脚本文件也放在跟jni平级的目录中去

其中:Android.mk文件的内容如下:

LOCAL_PATH := $(call my-dir) 
include $(CLEAR_VARS)

LOCAL_MODULE := hello_shared
LOCAL_MODULE_FILENAME := libhello
#设置可以使用C++代码
LOCAL_CPPFLAGS += -std=c++11

# 配置自己的源文件目录和源文件后缀名
    MY_FILES_PATH  :=  $(LOCAL_PATH) \
    $(LOCAL_PATH)/../../ClientSocketEngine

MY_FILES_SUFFIX := %.cpp %.c
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)


# 配置自己的源文件目录和源文件后缀名
MY_FILES_PATH  :=  $(LOCAL_PATH) \
                   $(LOCAL_PATH)/../../ClientSocketEngine

MY_FILES_SUFFIX := %.cpp %.c

# 递归遍历目录下的所有的文件
rwildcard=$(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2))
 
###################放置自己的cpp文件路径
MY_SRC_LIST = $(LOCAL_PATH)/../../sourceCode\sayHelloWorld.cpp 
###################   

# 去除字串的重复单词
define uniq =
  $(eval seen :=)
  $(foreach _,$1,$(if $(filter $_,${seen}),,$(eval seen += $_)))
  ${seen}
endef

# 递归遍历获取所有目录
MY_ALL_DIRS := $(dir $(foreach src_path,$(MY_FILES_PATH), $(call rwildcard,$(src_path),*/) ) )
MY_ALL_DIRS := $(call uniq,$(MY_ALL_DIRS))

# 赋值给NDK编译系统
LOCAL_SRC_FILES  := $(MY_SRC_LIST)
#头文件路径指向 
LOCAL_C_INCLUDES :=$(MY_ALL_DIRS)  

APP_ALLOW_MISSING_DEPS :=true
 
include $(BUILD_SHARED_LIBRARY)

Appication.mk的文件内容如下:

APP_STL := gnustl_static  
APP_CPPFLAGS := -frtti -DCOCOS2D_DEBUG=1 -fexceptions


build_native.bat脚本内容如下:

注意:NDK_ROOT是当前解压缩之后的ndk路径

@set "NDK_ROOT=D:\updatendk\android-ndk-r14b"

@set "DIR=%cd%"
@REM ... use paths relative to current directory
@set "APP_ROOT=%DIR%/.."
@set "APP_ANDROID_ROOT=%DIR%"

@echo NDK_ROOT = %NDK_ROOT%
@echo APP_ROOT = %APP_ROOT%
@echo APP_ANDROID_ROOT = %APP_ANDROID_ROOT%

@echo Using prebuilt externals
@"%NDK_ROOT%/ndk-build.cmd" 
pause

6)执行bat脚本:

成功之后会在jni平级的目录中会新增加libsobj文件夹,其中libs文件夹下就是要生成的对应android平台的libhello.so文件

so库编译成功之后就可以放入androidstudio环境中用jni调用了,调用步骤我们下篇文章继续讲述~

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以回答你关于在 Linux NDK 中交叉编译 SO 的问题。 在交叉编译 SO 之前,你需要先设置交叉编译环境。你可以使用以下命令来设置交叉编译环境: ``` ndk-build APP_ABI=armeabi-v7a NDK_TOOLCHAIN_VERSION=clang ``` 在这个命令中,`APP_ABI` 变量用来指定你要交叉编译的 ABI,这里我们选择了 `armeabi-v7a`,你可以根据你的需求选择其他 ABI。`NDK_TOOLCHAIN_VERSION` 变量用来指定你要使用的交叉编译工具链版本,这里我们选择了 `clang`,你也可以选择其他版本。 接下来,你需要编写一个 Makefile 文件来告诉交叉编译器如何编译你的 SO 。下面是一个简单的例子: ``` CROSS_COMPILE = $(NDK_TOOLCHAIN_PREFIX) CC = $(CROSS_COMPILE)gcc CFLAGS = -fPIC -Wall LDFLAGS = -shared LIB_SRC = my_lib.c LIB_OBJ = $(LIB_SRC:.c=.o) LIB_SO = libmy_lib.so all: $(LIB_SO) $(LIB_SO): $(LIB_OBJ) $(CC) $(LDFLAGS) -o $@ $< $(LIB_OBJ): $(LIB_SRC) $(CC) $(CFLAGS) -c $< -o $@ clean: rm -f $(LIB_SO) $(LIB_OBJ) ``` 在这个例子中,我们首先定义了交叉编译器前缀和编译器。在 `all` 目标中,我们告诉 Makefile 编译我们的 SO 文件。在 `$(LIB_SO)` 目标中,我们使用 `$(LDFLAGS)` 来告诉编译器生成一个共享文件。在 `$(LIB_OBJ)` 目标中,我们使用 `$(CFLAGS)` 来告诉编译器生成目标文件。 最后,你需要在 Linux NDK 中使用这个 Makefile 文件来交叉编译你的。你可以使用以下命令来交叉编译你的: ``` ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk ``` 在这个命令中,`NDK_PROJECT_PATH` 变量用来指定你的项目路径,`APP_BUILD_SCRIPT` 变量用来指定你的 Makefile 文件路径。 当编译完成后,你会在 `libs` 目录下找到你的 SO 文件。你可以将这个 SO 文件复制到你的应用程序中,并在代码中使用它。 希望这个回答能够帮助到你!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值