Linux android gun ndk下的so不同

so 与 so 是不同的。

Linux 与 Android 只是系统环境,不影响编译出的 so 。影响 so 能否使用是看用什么编译器,gun 编译出的与 ndk 编译出的 SO是不同的。

本文章只是实验  如何 Android 使用 JNI 封装的第三方 c 语言 so 库。

目前取得了第三方linux so 库。想在手机上使用此 so 库,必须使用 NDK 的 JNI 来封装此第三方 so 库。封装教程网上比比皆是,但是封装却始终提示:

一直认为名字都为 so ,不成功是步骤出了问题。试验了无数次我才幡然大悟,开始质疑 so 是否有差别的。这次实验就充分说明了不同编译器编译的 so 是不同的。要想实现我的目标,必须需要 NDK 来编译源码生成 so ,才能继续使用 ndk 的 jni 封装出Android 能用的 so 库。

直接上简单代码,c  与  cpp 是为了生成 c 的 so 和 c++ 的 so,他们共用一个头文件 h:

Atest.h
//本文件名


#ifndef ATEST_H
#define ATEST_H

 int MyFuck(int a);

#endif
Atest.cpp
//本文件名


#include"Atest.h"
int MyFuck(int a)
{
   return a+a;
}
Atest.c
//本文件名



#include"Atest.h"
int MyFuck(int a)
{
  return a+a;
}

一、linux下gun编译so:

Linux 下 gun 编译:g++ -fpic -shared -o libAtestcpp.so Atest.cpp   即可得到 c++ 的 libAtestcpp.so。

Linux 下 gun 编译:gcc -c -fPIC -o Atest.o Atest.c        

                            gcc -shared -o libAtestc.so Atest.o 即可得到 c 的 libAtestc.so。

现在我们看下这两个 so 有什么不同,linux 下用 file 名字.so 即可看到文件信息:

C++ 的:

c 的:

都是 elf 文件,64位。c 和 c++ 基本一样。

现在看看他们里面的函数是否一样,linux 下 nm -D 名字.so  即可看到里面的函数:

c++ 的:

c 的:

很清楚的看见同样函数 c 和 c++ 的 so 中动态库函数符号是明显不一样的。

因为用 gun 编译 so 肯定是不能用于NDK、不能用于jni、不能用于Android,所以接下的测试我已经完成但不再展示这种错误的做法:

在使用 NDK 的 jni 封装这个 libAtest.so 时,肯定是会报错的,因为 NDK 是识别不了 GUN 编译的 SO(大概吧)。

在封装 jni 时,报错界面:

实际错误为找不到 so 中我们自己写的函数

二、Windows下NDK编译so:

把上面三个源码用 NDK 编译,额外需要在源码目录下创建 jni 文件夹,创建 Android.mk 文件,内容为:

LOCAL_PATH := $(call my-dir)/.. #路径目录定为当前文件夹上层路径
LOCAL_LIB_PATH := $(call my-dir) #lib路径为当前路径
include $(CLEAR_VARS)             
LOCAL_MODULE := Atest             #生成的so名字
LOCAL_SRC_FILES := Atest.c        #从这个源码编成so,cpp就改成cpp
include $(BUILD_SHARED_LIBRARY)   #命令为建成 动态库

在 Android.mk 目录下运行 cmd,会自动在上一层目录生成 so 的文件夹:

obj 文件夹是中间生成物,libs 文件夹里面的是真正需要的 so 文件。图中 c 和 cpp 都生成了一下,我们只使用 c 的 so。cpp 的so 大家自己尝试吧。

c++ 的 so:

最后一行为 c++ 动态库函数符号

c 的 so:

再来比较两个 so 的文件信息:

可以看出差别不大,但是比我们用 gun 编译出的 so 多出了 ARM 架构。

接下来的步骤网上都是:如何 Android 使用 jni 封装的第三方 c 语言 so 库

我们需要刚才的生成的 c 的 so 库和我们的头文件 Atest.h :

com_sdk_HCNetSDK.h
//本文件名



/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_sdk_HCNetSDK */

#ifndef _Included_com_sdk_HCNetSDK
#define _Included_com_sdk_HCNetSDK
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_sdk_HCNetSDK
 * Method:    NET_DVR_Cleanup
 * Signature: ()Z
 */
JNIEXPORT jboolean JNICALL Java_com_sdk_HCNetSDK_NET_1DVR_1Cleanup
  (JNIEnv *, jobject);

/*
 * Class:     com_sdk_HCNetSDK
 * Method:    NET_DVR_Init
 * Signature: ()Z
 */
JNIEXPORT jboolean JNICALL Java_com_sdk_HCNetSDK_NET_1DVR_1Init
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif
HCNetSDK.cpp
//本文件名



#include"com_sdk_HCNetSDK.h"

extern "C" {

#include"Atest.h"

JNIEXPORT jboolean JNICALL Java_com_sdk_HCNetSDK_NET_1DVR_1Init
  (JNIEnv *, jobject)
{
		int a=999;
		int b=a;
		a=MyFuck(a);
		if(a==b)
		{return false;}
	else
{return true;}
		
}


JNIEXPORT jboolean JNICALL Java_com_sdk_HCNetSDK_NET_1DVR_1Cleanup
  (JNIEnv *, jobject)
	{
			return true;
	}

}

这里需要注意一下,要把我们的 Atest.h 用 extern "C" 修饰,变量和函数是按照 C 语言方式编译和链接的。

创建jni文件夹,里面新建 Android.mk 和 Application.mk 两个文件,内容为:

Android.mk
//本文件名


LOCAL_PATH := $(call my-dir)/..
LOCAL_LIB_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := test
LOCAL_SRC_FILES := $(LOCAL_LIB_PATH)/libAtest.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := NetDEVSDK_JNI
LOCAL_C_INCLUDES = -I $(LOCAL_PATH)/Atest.h com_sdk_HCNetSDK.h
#源文件
LOCAL_SRC_FILES += $(wildcard $(LOCAL_PATH)/HCNetSDK.cpp)
LOCAL_LDLIBS :=  -fPIC -shared -lc -lz
LOCAL_ALLOW_UNDEFINED_SYMBOLS:=true              #你还是乖乖加上这个吧
LOCAL_SHARED_LIBRARIES += test
include $(BUILD_SHARED_LIBRARY)
Application.mk
//本文件名


APP_ABI := armeabi armeabi-v7a x86 mips mips64 x86_64 arm64-v8a

APP_CPPFLAGS += -frtti

APP_PLATFORM := android-9
APP_STL := gnustl_static 

在 jni 文件夹里运行 cmd,执行 ndk-build 命令。即可生成我们需要的 libNetDEVSDK_JNI.so 文件。

这里的报错是因为架构不支持,我们最少获得了 libs 文件夹中的 armeabi 和 armeabi-v7a 架构的so。

正常使用时需要我们生成的两个so文件,Android 调用 libNetDEVSDK_JNI.so 内函数,libNetDEVSDK_JNI.so  调用 libAtest.so 文件内函数。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值