当前位置:首页 » 编程软件 » 安卓预编译动态库中间路径

安卓预编译动态库中间路径

发布时间: 2023-05-30 00:17:45

1. Android常见的预编译(prebuilt)

android常用的预编译方法(prebuilt)

1.framework引入静态jar包

2.编译共享jar包

3.编译so库
方法1 : 单独编译

方法2 : 轮询编译

4.预编译apk
预置apk至系统,如果apk含有so库的话,也需要提前编译到系统中,解压apk文件,将so提取出来放置某一文件夹中,通过LOCAL_PREBUILT_JNI_LIBS将so编译至system/app/package/lib/arm目录

2. android 怎么编译so文件

android NDK编译多个so文件

android编译系统的makefile文件Android.mk写法如下

(1)Android.mk文件首先需要指定LOCAL_PATH变量,用于查找源文件。由于一般情况下

Android.mk和需要编译的源文件在同一目录下,所以定义成如下形式:

LOCAL_PATH:=$(call my-dir)

上面的语句的意思是将LOCAL_PATH变量定义成本文件所在目录路径。

(2)Android.mk中可以定义多个编译模块,每个编译模块都是以include $(CLEAR_VARS)开始

以include $(BUILD_XXX)结束。

include $(CLEAR_VARS)

CLEAR_VARS由编译系统提供,指定让GNU MAKEFILE为你清除除LOCAL_PATH以外的所有LOCAL_XXX变量,

如LOCAL_MODULE,LOCAL_SRC_FILES,LOCAL_SHARED_LIBRARIES,LOCAL_STATIC_LIBRARIES等。

include $(BUILD_STATIC_LIBRARY)表示编译成静态库

include $(BUILD_SHARED_LIBRARY)表示编译成动态库。

include $(BUILD_EXECUTABLE)表示编译成可执行程序

(3)举例如下(frameworks/base/libs/audioflinger/Android.mk):

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS) 模块一

ifeq ($(AUDIO_POLICY_TEST),true)

ENABLE_AUDIO_DUMP := true

endif

LOCAL_SRC_FILES:= \

AudioHardwareGeneric.cpp \

AudioHardwareStub.cpp \

AudioHardwareInterface.cpp

ifeq ($(ENABLE_AUDIO_DUMP),true)

LOCAL_SRC_FILES += AudioDumpInterface.cpp

LOCAL_CFLAGS += -DENABLE_AUDIO_DUMP

endif

LOCAL_SHARED_LIBRARIES := \

libcutils \

libutils \

libbinder \

libmedia \

libhardware_legacy

ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true)

LOCAL_CFLAGS += -DGENERIC_AUDIO

endif

LOCAL_MODULE:= libaudiointerface

ifeq ($(BOARD_HAVE_BLUETOOTH),true)

LOCAL_SRC_FILES += A2dpAudioInterface.cpp

LOCAL_SHARED_LIBRARIES += liba2dp

LOCAL_CFLAGS += -DWITH_BLUETOOTH -DWITH_A2DP

LOCAL_C_INCLUDES += $(call include-path-for, bluez)

endif

include $(BUILD_STATIC_LIBRARY) 模块一编译成静态库

include $(CLEAR_VARS) 模块二

LOCAL_SRC_FILES:= \

AudioPolicyManagerBase.cpp

LOCAL_SHARED_LIBRARIES := \

libcutils \

libutils \

libmedia

ifeq ($(TARGET_SIMULATOR),true)

LOCAL_LDLIBS += -ldl

else

LOCAL_SHARED_LIBRARIES += libdl

endif

LOCAL_MODULE:= libaudiopolicybase

ifeq ($(BOARD_HAVE_BLUETOOTH),true)

LOCAL_CFLAGS += -DWITH_A2DP

endif

ifeq ($(AUDIO_POLICY_TEST),true)

LOCAL_CFLAGS += -DAUDIO_POLICY_TEST

endif

include $(BUILD_STATIC_LIBRARY) 模块二编译成静态库

include $(CLEAR_VARS) 模块三

LOCAL_SRC_FILES:= \

AudioFlinger.cpp \

AudioMixer.cpp.arm \

AudioResampler.cpp.arm \

AudioResamplerSinc.cpp.arm \

AudioResamplerCubic.cpp.arm \

AudioPolicyService.cpp

LOCAL_SHARED_LIBRARIES := \

libcutils \

libutils \

libbinder \

libmedia \

libhardware_legacy

ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true)

LOCAL_STATIC_LIBRARIES += libaudiointerface libaudiopolicybase

LOCAL_CFLAGS += -DGENERIC_AUDIO

else

LOCAL_SHARED_LIBRARIES += libaudio libaudiopolicy

endif

ifeq ($(TARGET_SIMULATOR),true)

LOCAL_LDLIBS += -ldl

else

LOCAL_SHARED_LIBRARIES += libdl

endif

LOCAL_MODULE:= libaudioflinger

ifeq ($(BOARD_HAVE_BLUETOOTH),true)

LOCAL_CFLAGS += -DWITH_BLUETOOTH -DWITH_A2DP

LOCAL_SHARED_LIBRARIES += liba2dp

endif

ifeq ($(AUDIO_POLICY_TEST),true)

LOCAL_CFLAGS += -DAUDIO_POLICY_TEST

endif

ifeq ($(TARGET_SIMULATOR),true)

ifeq ($(HOST_OS),linux)

LOCAL_LDLIBS += -lrt -lpthread

endif

endif

ifeq ($(BOARD_USE_LVMX),true)

LOCAL_CFLAGS += -DLVMX

LOCAL_C_INCLUDES += vendor/nxp

LOCAL_STATIC_LIBRARIES += liblifevibes

LOCAL_SHARED_LIBRARIES += liblvmxservice

# LOCAL_SHARED_LIBRARIES += liblvmxipc

endif

include $(BUILD_SHARED_LIBRARY) 模块三编译成动态库

(4)编译一个应用程序(APK)

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

# Build all java files in the java subdirectory-->直译(建立在java子目录中的所有Java文件)

LOCAL_SRC_FILES := $(call all-subdir-java-files)

# Name of the APK to build-->直译(创建APK的名称)

LOCAL_PACKAGE_NAME := LocalPackage

# Tell it to build an APK-->直译(告诉它来建立一个APK)

include $(BUILD_PACKAGE)

(5)编译一个依赖于静态Java库(static.jar)的应用程序

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

# List of static libraries to include in the package

LOCAL_STATIC_JAVA_LIBRARIES := static-library

# Build all java files in the java subdirectory

LOCAL_SRC_FILES := $(call all-subdir-java-files)

# Name of the APK to build

LOCAL_PACKAGE_NAME := LocalPackage

# Tell it to build an APK

include $(BUILD_PACKAGE)

(6)编译一个需要用平台的key签名的应用程序

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

# Build all java files in the java subdirectory

LOCAL_SRC_FILES := $(call all-subdir-java-files)

# Name of the APK to build

LOCAL_PACKAGE_NAME := LocalPackage

LOCAL_CERTIFICATE := platform

# Tell it to build an APK

include $(BUILD_PACKAGE)

(7)编译一个需要用特定key前面的应用程序

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

# Build all java files in the java subdirectory

LOCAL_SRC_FILES := $(call all-subdir-java-files)

# Name of the APK to build

LOCAL_PACKAGE_NAME := LocalPackage

LOCAL_CERTIFICATE := vendor/example/certs/app

# Tell it to build an APK

include $(BUILD_PACKAGE)

(8)添加一个预编译应用程序

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

# Mole name should match apk name to be installed.

LOCAL_MODULE := LocalMoleName

LOCAL_SRC_FILES := $(LOCAL_MODULE).apk

LOCAL_MODULE_CLASS := APPS

LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)

include $(BUILD_PREBUILT)

(9)添加一个静态JAVA库

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

# Build all java files in the java subdirectory

LOCAL_SRC_FILES := $(call all-subdir-java-files)

# Any libraries that this library depends on

LOCAL_JAVA_LIBRARIES := android.test.runner

# The name of the jar file to create

LOCAL_MODULE := sample

# Build a static jar file.

include $(BUILD_STATIC_JAVA_LIBRARY)

(10)Android.mk的编译模块中间可以定义相关的编译内容,也就是指定相关的变量如下:

LOCAL_AAPT_FLAGS

LOCAL_ACP_UNAVAILABLE

LOCAL_ADDITIONAL_JAVA_DIR

LOCAL_AIDL_INCLUDES

LOCAL_ALLOW_UNDEFINED_SYMBOLS

LOCAL_ARM_MODE

LOCAL_ASFLAGS

LOCAL_ASSET_DIR

LOCAL_ASSET_FILES 在Android.mk文件中编译应用程序(BUILD_PACKAGE)时设置此变量,表示资源文件,

通常会定义成LOCAL_ASSET_FILES += $(call find-subdir-assets)

LOCAL_BUILT_MODULE_STEM

LOCAL_C_INCLUDES 额外的C/C++编译头文件路径,用LOCAL_PATH表示本文件所在目录

举例如下:

LOCAL_C_INCLUDES += extlibs/zlib-1.2.3

LOCAL_C_INCLUDES += $(LOCAL_PATH)/src

LOCAL_CC 指定C编译器

LOCAL_CERTIFICATE 签名认证

LOCAL_CFLAGS 为C/C++编译器定义额外的标志(如宏定义),举例:LOCAL_CFLAGS += -DLIBUTILS_NATIVE=1

LOCAL_CLASSPATH

LOCAL_COMPRESS_MODULE_SYMBOLS

LOCAL_COPY_HEADERS install应用程序时需要复制的头文件,必须同时定义LOCAL_COPY_HEADERS_TO

LOCAL_COPY_HEADERS_TO install应用程序时复制头文件的目的路径

LOCAL_CPP_EXTENSION 如果你的C++文件不是以cpp为文件后缀,你可以通过LOCAL_CPP_EXTENSION指定C++文件后缀名

如:LOCAL_CPP_EXTENSION := .cc

注意统一模块中C++文件后缀必须保持一致。

LOCAL_CPPFLAGS 传递额外的标志给C++编译器,如:LOCAL_CPPFLAGS += -ffriend-injection

LOCAL_CXX 指定C++编译器

LOCAL_DX_FLAGS

LOCAL_EXPORT_PACKAGE_RESOURCES

LOCAL_FORCE_STATIC_EXECUTABLE 如果编译的可执行程序要进行静态链接(执行时不依赖于任何动态库),则设置LOCAL_FORCE_STATIC_EXECUTABLE:=true

目前只有libc有静态库形式,这个只有文件系统中/sbin目录下的应用程序会用到,这个目录下的应用程序在运行时通常

文件系统的其它部分还没有加载,所以必须进行静态链接。

LOCAL_GENERATED_SOURCES

LOCAL_INSTRUMENTATION_FOR

LOCAL_INSTRUMENTATION_FOR_PACKAGE_NAME

LOCAL_INTERMEDIATE_SOURCES

LOCAL_INTERMEDIATE_TARGETS

LOCAL_IS_HOST_MODULE

LOCAL_JAR_MANIFEST

LOCAL_JARJAR_RULES

LOCAL_JAVA_LIBRARIES 编译java应用程序和库的时候指定包含的java类库,目前有core和framework两种

多数情况下定义成:LOCAL_JAVA_LIBRARIES := core framework

注意LOCAL_JAVA_LIBRARIES不是必须的,而且编译APK时不允许定义(系统会自动添加)

LOCAL_JAVA_RESOURCE_DIRS

LOCAL_JAVA_RESOURCE_FILES

LOCAL_JNI_SHARED_LIBRARIES

LOCAL_LDFLAGS 传递额外的参数给连接器(务必注意参数的顺序)

LOCAL_LDLIBS 为可执行程序或者库的编译指定额外的库,指定库以"-lxxx"格式,举例:

LOCAL_LDLIBS += -lcurses -lpthread

LOCAL_LDLIBS += -Wl,-z,origin

LOCAL_MODULE 生成的模块的名称(注意应用程序名称用LOCAL_PACKAGE_NAME而不是LOCAL_MODULE)

LOCAL_MODULE_PATH 生成模块的路径

LOCAL_MODULE_STEM

LOCAL_MODULE_TAGS 生成模块的标记

LOCAL_NO_DEFAULT_COMPILER_FLAGS

LOCAL_NO_EMMA_COMPILE

LOCAL_NO_EMMA_INSTRUMENT

LOCAL_NO_STANDARD_LIBRARIES

LOCAL_OVERRIDES_PACKAGES

LOCAL_PACKAGE_NAME APK应用程序的名称

LOCAL_POST_PROCESS_COMMAND

LOCAL_PREBUILT_EXECUTABLES 预编译including $(BUILD_PREBUILT)或者$(BUILD_HOST_PREBUILT)时所用,指定需要复制的可执行文件

LOCAL_PREBUILT_JAVA_LIBRARIES

LOCAL_PREBUILT_LIBS 预编译including $(BUILD_PREBUILT)或者$(BUILD_HOST_PREBUILT)时所用, 指定需要复制的库.

LOCAL_PREBUILT_OBJ_FILES

LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES

LOCAL_PRELINK_MODULE 是否需要预连接处理(默认需要,用来做动态库优化)

LOCAL_REQUIRED_MODULES 指定模块运行所依赖的模块(模块安装时将会同步安装它所依赖的模块)

LOCAL_RESOURCE_DIR

LOCAL_SDK_VERSION

LOCAL_SHARED_LIBRARIES 可链接动态库

LOCAL_SRC_FILES 编译源文件

LOCAL_STATIC_JAVA_LIBRARIES

LOCAL_STATIC_LIBRARIES 可链接静态库

LOCAL_UNINSTALLABLE_MODULE

LOCAL_UNSTRIPPED_PATH

LOCAL_WHOLE_STATIC_LIBRARIES 指定模块所需要载入的完整静态库(这些精通库在链接是不允许链接器删除其中无用的代码)

LOCAL_YACCFLAGS

OVERRIDE_BUILT_MODULE_PATH

3. ndk-Android NDk 怎么编译时动态链接第三方so库,有头文件

问题描述:Android如何调用第三方SO库;
已知条件:SO库为Android版本连接库(*.so文件),并提供了详细的接口说明;
已了解解决方案:
1.将SO文件直接放到libs/armeabi下,然后代码中System.loadLibrary("xxx");再public native static int xxx_xxx_xxx();接下来就可以直接调用xxx_xxx_xxx()方法;
2.第二种方案,创建自己的SO文件,在自己的SO文件里调用第三方SO,再在程序中调用自己的SO,这种比较复杂,需要建java类文件,生成.h文件,编写C源文件include之前生成的.h文件并实现相应方法,最后用android NDK开发包中的ndk-build脚本生成对应的.so共享库;
求解:
1.上面两种方案是否可行?不可行的话存在什么问题?
2.两种方案有什么区别?为什么网上大部都是用的第二种方案?
3.只有一个*.so文件,并提供了详细的接口说明,是否可在ANDROID中使用它?

首先要看这个SO是不是JNI规范的SO,比如有没有返回JNI不直接支持的类型。也就是说这个SO是不是可以直接当作JNI来调用。如果答案是否定的,你只能选第二个方案。

如果答案是肯定的,还要看你是不是希望这个SO的库直接暴露给JAVA层,如果答案是否定的,你只能选第二个方案,比如你本身也是一个库的提供者。

一般如果你只有SO,就说明这个是别人提供给你的,你可以要求对方给你提供配套的JAVA调用文件。

1、这个要看这个SO是不是符合JNI调用的规范。还要看你自己的意愿。
2、因为第二种方法最灵活,各种情况都可以实现。
3、可以

看能不能直接从JAVA调用的最简单的方法就是看SO里的函数名是不是Java_XXX_XXX_XXX格式的
是就可以,你可以自己写一个配套的JAVA文件,注意一下SO函数名和JAVA函数名的转换规则,或者向SO提供方索要;
不是的话就选第二种方案吧。

1、检查所需文件是否齐全
使用第三方动态库,应该至少有2个文件,一个是动态库(.so),另一个是包含
动态库API声明的头文件(.h)
2、封装原动态库
原动态库文件不包含jni接口需要的信息,所以我们需要对其进行封装,所以我
们的需求是:将libadd.so 里面的API封装成带jni接口的动态
3、编写库的封装函数libaddjni.c
根据前面生成的com_android_libjni_LibJavaHeader.h 文件,编写libaddjni.c,用
来生成libaddjni.so

Android中集成第三方软件包(.jar, .so)

Android中可能会用到第三方的软件包,这包括Java包.jar和Native包.so。jar包既可通过Eclipse开发环境集成,也可通过编译源码集成,看你的工作环境。

假定自己开发的程序为MyMaps,需要用到BaiMaps的库,包括mapapi.jar和libBMapApiEngine_v1_3_1.so。

一、Eclipse中集成第三方jar包及.so动态库

MyMaps工程下创建目录libs以及libs/armeabi,把mapapi.jar放在的libs/目录下,把libBMapApiEngine_v1_3_1.so放在libs/armeabi/下。

Eclipse中把第三方jar包mapapi.jar打包到MyMaps的步骤:

1. 右击工程,选择Properties;
2. Java Build Path,选择Libraries;
3. Libraries页面点击右面按钮“Add Library…”;
4. 选择“User Library”,点击“Next”;
5. 点击“User Libraries”按钮;
6. 在弹出界面中,点击“New…”;
7. 输入“User library name”,点击“OK”确认;
8. 返回之后,选择刚刚创建的User library,右面点击“AddJARs”;
9. 选择MyMaps/libs/下的mapapi.jar;
10. 确认,返回。

这样,编译之后,该jar包就会被打进MyMaps.apk中,libBMapApiEngine_v1_3_1.so也被打包在lib/armeabi/中。
程序运行过程中,libBMapApiEngine_v1_3_1.so被放在/data/data/<yourAppPackage>/lib/下,加载动态库时系统会从程序的该lib/目录下查找.so库。

二、源码中集成第三方集成jar包及.so动态库

Android源码中MyMaps放在packages/apps下。MyMaps下创建目录libs以及libs/armeabi,并把mapapi.jar放在libs/,把libBMapApiEngine_v1_3_1.so放在libs/armeabi。

2.1 修改Android.mk文件

Android.mk文件如下:

[plain] view plain
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional

LOCAL_STATIC_JAVA_LIBRARIES := libmapapi

LOCAL_SRC_FILES := $(call all-subdir-java-files)

LOCAL_PACKAGE_NAME := MyMaps

include $(BUILD_PACKAGE)

##################################################
include $(CLEAR_VARS)

LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES :=libmapapi:libs/mapapi.jar
LOCAL_PREBUILT_LIBS :=libBMapApiEngine_v1_3_1:libs/armeabi/libBMapApiEngine_v1_3_1.so
LOCAL_MODULE_TAGS := optional
include $(BUILD_MULTI_PREBUILT)

# Use the following include to make our testapk.
include $(callall-makefiles-under,$(LOCAL_PATH))

1 集成jar包
LOCAL_STATIC_JAVA_LIBRARIES取jar库的别名,可以任意取值;
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES指定prebuiltjar库的规则,格式:别名:jar文件路径。注意:别名一定要与LOCAL_STATIC_JAVA_LIBRARIES里所取的别名一致,且不含.jar;jar文件路径一定要是真实的存放第三方jar包的路径。
编译用BUILD_MULTI_PREBUILT。
2 集成.so动态库
LOCAL_PREBUILT_LIBS指定prebuilt so的规则,格式:别名:so文件路径。注意:别名一般不可改变,特别是第三方jar包使用.so库的情况,且不含.so;so文件路径一定要是真实的存放第三方so文件的路径。
编译拷贝用BUILD_MULTI_PREBUILT。

2.2 加入到GRANDFATHERED_USER_MODULES

在文件user_tags.mk中,把libBMapApiEngine_v1_3_1加入到GRANDFATHERED_USER_MODULES中

[plain] view plain
GRANDFATHERED_USER_MODULES += \
… \
libBMapApiEngine_v1_3_1

user_tags.mk可以是build/core下的,也可以是$(TARGET_DEVICE_DIR)下的,推荐修改$(TARGET_DEVICE_DIR)下的。

2.3 编译结果

MyMaps.apk编译生成在out/target/proct/<YourProct>/system/app/下;
libBMapApiEngine_v1_3_1.so放在out/target/proct/<YourProct>/system/lib/下,这也是系统加载动态库时搜索的路径。

4. 用arm-linux交叉编译器使用动态库时搜索标准路径是什么

/usr/lib , /橘源usr/libxx xx为数字,一般32或64,x32
标准头好伍毕文友芹件搜索路径:/usr/include/

5. androidbp如何添加库路径

androidbp在设置中添加库路饥纳培径,具体步骤如下:
1、androidbp添加库茄蔽路径通过设置进行。
2、点击进入设置页面,下拉,找到库路径,进行设烂唯置即可。

6. android的jni放哪个文件夹

原java语言编写的类仍放工程的src文件目录下,方法用native关键字进行修饰,编译后生成.class文件,在java类中通过静态块引入其调用的本地方法,引入如下:
public class Test{
static {
system.loadlibrary("name"); //引入动态库的名字
}
public native int hello(String str[]);
}
通过用C语言编写的JNI方法的头文件要包含java类通过java -h进行编译后的头文件。编写完JNI方法后,通过编译工具生成动态库文件(name.dll文件或name.so文件)(例如可把其放到jdk\bin目录下,也可把动态库放到工程同classes同文件夹的目录下),把该文件放于系统环境变量path中路径所在文件中,即可引入。

7. 编译时找不到动态库

报错:

分析:
  应该是动态库链接的库位置不对,默认在目录usr/lib/ 下查找动态库。

方式一 用ln -s建立创建软连接,确保/usr/lib下存在库。
  ln -s /绝对路径/源 /绝对路径/目的
方式二 编译时使用-rpath 或者-rpath-link,例如如下gcc编译时设置
mips64el-redhat-linux-gcc -o test *.c -Wall -L./lib/mips64le/ -lpthread -lm -Wl,-rpath=/usr/local/gcc-4.8.3-d197-n64-loongson/usr/mips64el-redhat-linux/lib64/

挂载命令的顺序

8. 关于动态库 静态库 区别与使用 路径查找等

一、引言

我们通常把一些公用函数制作成函数库,供其它程序使用。
函数库分为静态库和动态库两种。

通常情况下,对函数库的链接是放在编译时期(compile time)完成的。所有相关的对象文件(object file)与牵涉到的函数库(library)被链接合成一个可执行文件(executable file)。程序在运行时,与函数库再无瓜葛,因为所有需要的函数已拷贝到相应目录下下。所以这些函数库被成为静态库(static libaray),通常文件名为“libxxx.a”的形式。

其实,我们也可以把对一些库函数的链接载入推迟到程序运行的时期(runtime)。这就是动态链接库(dynamic link library)技术。

二、两者区别:
a,静态库的使用需要:
1 包含一个对应的头文件告知编译器lib文件里面的具体内容
2 设置lib文件允许编译器去查找已经编译好的二进制代码

b,动态库的使用:
程序运行时需要加载动态库,对动态库有依赖性,需要手动加入动态库

c,依赖性:
静态链接表示静态性,在编译链接之后, lib库中需要的资源已经在可执行程序中了, 也就是静态存在,没有依赖性了
动态,就是实时性,在运行的时候载入需要的资源,那么必须在运行的时候提供 需要的 动态库,有依赖性, 运行时候没有找到库就不能运行了

d,区别:
简单讲,静态库就是直接将需要的代码连接进可执行程序;动态库就是在需要调用其中的函数时,根据函数映射表找到该函数然后调入堆栈执行。
做成静态库可执行文件本身比较大,但不必附带动态库
做成动态库可执行文件本身比较小,但需要附带动态库
链接静态库,编译的可执行文件比较大,当然可以用strip命令精简一下(如:strip libtest.a),但还是要比链接动态库的可执行文件大。程序运行时间速度稍微快一点。
静态库是程序运行的时候已经调入内存,不管有没有调用,都会在内存里头。静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。
其在编译程序时若链接,程序运行时会在系统指定的路径下搜索,然后导入内存,程序一般执行时间稍微长一点,但编译的可执行文件比较小;动态库是程序运行的时候需要调用的时候才装入内存,不需要的时候是不会装入内存的。
动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。

三、动态链接库的特点与优势

首先让我们来看一下,把库函数推迟到程序运行时期载入的好处:

1. 可以实现进程之间的资源共享。

什么概念呢?就是说,某个程序的在运行中要调用某个动态链接库函数的时候,操作系统首先会查看所有正在运行的程序,看在内存里是否已有此库函数的拷贝了。如果有,则让其共享那一个拷贝;只有没有才链接载入。这样的模式虽然会带来一些“动态链接”额外的开销,却大大的节省了系统的内存资源。C的标准库就是动态链接库,也就是说系统中所有运行的程序共享着同一个C标准库的代码段。

2. 将一些程序升级变得简单。用户只需要升级动态链接库,而无需重新编译链接其他原有的代码就可以完成整个程序的升级。Windows 就是一个很好的例子。

3. 甚至可以真正坐到链接载入完全由程序员在程序代码中控制。

程序员在编写程序的时候,可以明确的指明什么时候或者什么情况下,链接载入哪个动态链接库函数。你可以有一个相当大的软件,但每次运行的时候,由于不同的操作需求,只有一小部分程序被载入内存。所有的函数本着“有需求才调入”的原则,于是大大节省了系统资源。比如现在的软件通常都能打开若干种不同类型的文件,这些读写操作通常都用动态链接库来实现。在一次运行当中,一般只有一种类型的文件将会被打开。所以直到程序知道文件的类型以后再载入相应的读写函数,而不是一开始就将所有的读写函数都载入,然后才发觉在整个程序中根本没有用到它们。

静态库:在编译的时候加载生成目标文件,在运行时不用加载库,在运行时对库没有依赖性。
动态库:在目标文件运行时加载,手动加载,且对库有依赖性。

具体在开发中用到哪种库,我觉得还是根据实际的内存大小,ROM大小,运行的速度等综合考虑。

9. Android Native库的加载及动态链接

我们从一个简单的NDK Demo开始分析。

下面从 System.loadLibrary() 开始分析。

下面看 loadLibrary0()

参数 loader 为Android的应用类加载器,它是 PathClassLoader 类型的对象,继承自 BaseDexClassLoader 对象,下面看 BaseDexClassLoader 的 findLibrary() 方法。

下面看 DexPathList 的 findLibrary() 方法

回到 loadLibrary0() ,有了动态库的全路径名就可以装载库了,下面看 doLoad() 。

nativeLoad() 最终调用 LoadNativeLibrary() ,下面直接分析 LoadNativeLibrary() 。

对于JNI注册,这里暂不讨论,下面看 OpenNativeLibrary() 的实现。

下面看 android_dlopen_ext() 的实现

接下来就Android链接器linker的工作了。

下面从 do_dlopen() 开始分析。

find_library() 当参数translated_name不为空时,直接调用 find_libraries() ,这是装载链接的关键函数,下面看它的实现。

find_libraries() 中动态库的装载可以分为两部分

下面从 find_library_internal() 开始分析。

下面分析 load_library()

下面看另一个 load_library() 的实现

下面分析ELF文件头以及段信息的读取过程,也就是LoadTask的 read() ,它直接调用ElfReader的 Read() 方法。

动态库的装载在LoadTask的 load() 中实现。

下面看ElfReader的 Load() 方法

动态库的装载已经完成,下面看链接过程。

下面看 prelink_image()

链接主要完成符号重定位工作,下面从 link_image() 开始分析

下面以函数引用重定位为例分析 relocate() 方法

10. 请教关于android linux动态库.so的加载调用

1、 .so动态库的生成
可使用gcc或者g++编译器生成动态库文件(此处以g++编译器为例)
g++ -shared -fPIC -c XXX.cpp
g++ -shared -fPIC -o XXX.so XXX.o
2、 .so动态库的动态调用接口函数说明
动态库的调用关系可以在需要调用动态库的程序编译时,通过g++的-L和-l命令来指定。例如:程序test启动时需要加载目录/root/src/lib中的libtest_so1.so动态库,编译命令可照如下编写执行:
g++ -g -o test test.cpp –L/root/src/lib –ltest_so1
(此处,我们重点讲解动态库的动态调用的方法,关于静态的通过g++编译命令调用的方式不作详细讲解,具体相关内容可上网查询)

Linux下,提供专门的一组API用于完成打开动态库,查找符号,处理出错,关闭动态库等功能。
下面对这些接口函数逐一介绍(调用这些接口时,需引用头文件#include <dlfcn.h>):
1) dlopen
函数原型:void *dlopen(const char *libname,int flag);
功能描述:dlopen必须在dlerror,dlsym和dlclose之前调用,表示要将库装载到内存,准备使用。如果要装载的库依赖于其它库,必须首先装载依赖库。如果dlopen操作失败,返回NULL值;如果库已经被装载过,则dlopen会返回同样的句柄。
参数中的libname一般是库的全路径,这样dlopen会直接装载该文件;如果只是指定了库名称,在dlopen会按照下面的机制去搜寻:
a.根据环境变量LD_LIBRARY_PATH查找
b.根据/etc/ld.so.cache查找
c.查找依次在/lib和/usr/lib目录查找。
flag参数表示处理未定义函数的方式,可以使用RTLD_LAZY或RTLD_NOW。RTLD_LAZY表示暂时不去处理未定义函数,先把库装载到内存,等用到没定义的函数再说;RTLD_NOW表示马上检查是否存在未定义的函数,若存在,则dlopen以失败告终。
2) dlerror
函数原型:char *dlerror(void);
功能描述:dlerror可以获得最近一次dlopen,dlsym或dlclose操作的错误信息,返回NULL表示无错误。dlerror在返回错误信息的同时,也会清除错误信息。
3) dlsym
函数原型:void *dlsym(void *handle,const char *symbol);
功能描述:在dlopen之后,库被装载到内存。dlsym可以获得指定函数(symbol)在内存中的位置(指针)。如果找不到指定函数,则dlsym会返回NULL值。但判断函数是否存在最好的方法是使用dlerror函数,
4) dlclose
函数原型:int dlclose(void *);
功能描述:将已经装载的库句柄减一,如果句柄减至零,则该库会被卸载。如果存在析构函数,则在dlclose之后,析构函数会被调用。
3、 普通函数的调用
此处以源码实例说明。各源码文件关系如下:
test_so1.h和test_so1.cpp生成test_so1.so动态库。
test_so2.h和test_so2.cpp生成test_so2.so动态库。
test_dl.cpp生成test_dl可执行程序,test_dl通过dlopen系列等API函数,并使用函数指针以到达动态调用不同so库中test函数的目的。

热点内容
高级语言都要编译解析型语言 发布:2025-02-13 15:06:32 浏览:304
openwrt源码下载 发布:2025-02-13 15:01:59 浏览:644
linux删除一个目录 发布:2025-02-13 15:00:29 浏览:539
蚂蚁存储 发布:2025-02-13 15:00:25 浏览:918
脚本师传奇 发布:2025-02-13 14:45:48 浏览:481
我的世界lce服务器剪辑 发布:2025-02-13 14:40:50 浏览:625
phpsftp上传 发布:2025-02-13 14:35:43 浏览:274
c学生管理系统数据库 发布:2025-02-13 14:21:41 浏览:123
传奇添加会员脚本 发布:2025-02-13 14:20:50 浏览:206
微信开发平台源码 发布:2025-02-13 14:14:20 浏览:614