一、动态库的构建步骤

① 创建动态库

  • 创建一个动态库 MyDynamicFramework:

  • 创建一个测试类:

  • 在 MyDynamicFramework.h(默认生成,可统一暴露头文件) 中 #import “Person.h”:
   #import <Foundation/Foundation.h>//! Project version number for MyDynamicFramework.FOUNDATION_EXPORT double MyDynamicFrameworkVersionNumber;//! Project version string for MyDynamicFramework.FOUNDATION_EXPORT const unsigned char MyDynamicFrameworkVersionString[];// In this header, you should import all the public headers of your framework using statements like #import <MyDynamicFramework/PublicHeader.h>#import "Person.h"
  • 点击工程 -> Targets -> Build Phases -> Headers,动态库中新建的文件会自动添加到 project 列表,MyDynamicFramework.h 文件是处于 Public 列表中。由于动态库外部使用者需要调用 Person.h 中的方法,所以也需要将 Person.h 拖拽到 Public 列表,如下所示:

② 编译动态库

  • 选择动态库对应的 Scheme,选择 Generic iOS Device 或真机编译出对应真机的动态库,Command + B 编译。
  • 如果没有连接真机,也可以,只要选择Generic iOS Device选项也是可以编译出对应真机的动态库,如下图所示:

  • 在 Xcode 工程中的 Products(这个目录不是工程源文件目录,而是编译后生成对应的沙盒目录)找到 MyDynamicFramework.framework 文件,右键 show in finder:

  • 利用 lipo -info 查看动态库所支持的 CPU 指令集(在终端中,cd 进入 MyDynamicFramework.framework,这里需要注意进入的是 MyDynamicFramework.framework,而不是 MyDynamicFramework.framework 所在目录,
    然后输入 $lipo -info MyDynamicFramework),如下:
    lipo -info /Users/ydw/Library/Developer/Xcode/DerivedData/MyDynamicFramework-cnfmjshbkauwwshdqagjwrgypile/Build/Products/Debug-iphoneos/MyDynamicFramework.framework/MyDynamicFrameworkArchitectures in the fat file: /Users/ydw/Library/Developer/Xcode/DerivedData/MyDynamicFramework-cnfmjshbkauwwshdqagjwrgypile/Build/Products/Debug-iphoneos/MyDynamicFramework.framework/MyDynamicFramework are: arm7、arm64
  • 新建工程后所编译出来的动态库所支持的 CPU 指令集是 arm7、arm64。需要注意:lipo -info [文件] 后面跟的是文件路径,而不是 .framework 路径。

③ 指令集

  • 指令集种类:
    • armv7|armv7s|arm64 都是 ARM 处理器的指令集;
    • i386|x86_64 是 iOS 模拟器的指令集。
  • 指令集对应的机型:
arm64:iPhone6s | iphone6s plus|iPhone6| iPhone6 plus|iPhone5S | iPad Air| iPad mini2(iPad mini with Retina Display)
armv7s:iPhone5|iPhone5C|iPad4(iPad with Retina Display)
armv7:iPhone4|iPhone4S|iPad|iPad2|iPad3(The New iPad)|iPad mini|iPod Touch 3G|iPod Touch4i386: iPhone5 | iPhone 4s | iPhone 4及前代产品的模拟器
x86_64: iPhone5s | iPhone 6 | ... | iPhone8的模拟器
  • 理论上指令集是向下兼容的,比如连接设备为 arm64,那么是有可能编译出的动态库所支持的指令集为 armv7s 或者是 armv7。但是向下兼容并不是说一个 armv7s 的动态库可以用在 arm64 架构的设备上,如果连接的设备是 arm64 的,而导入的动态库是没有支持 arm64,那么在编译阶段即会报错。

④ Xcode 指令集的编译选项说明

  • Xcode 指令集的编译选项,打开 Target -> Build Setting -> Architectures,如下所示:

  • 说明:
    • Architectures:指明选定 Target 要求被编译生成的二进制包所支持的指令集;
    • Build Active Architecture Only:指明是否只编译当前连接设备所支持的指令集,如果为 YES,那么只编译出连接设备所对应的指令集;如果为 NO,则编译出所有其它有效的指令集(由 Architectures 和 Valid Architectures 决定);
    • Valid Architectures:指明可能支持的指令集并非 Architectures 列表中指明的指令集都会被支持。
  • 编译产生的动态库所支持的指令集将由上面三个编译选项所影响,首先一个动态库要成功编译,则需要这三个编译选项的交集不为空。如下所示:
示例1Architectures 为armv7、arm64Valid Architectures 为armv7、armv7s、arm64Build Active Architecture Only 为 debug:YES release:NO链接设备:iPhone 6s (arm64架构的设备)编译(command + shift + B,保证Build Active Architecture Only 为 debug:YES 生效)结果:编译成功,生成的动态库支持的指令集为arm64示例2Architectures 为armv7、arm64Valid Architectures 为 armv7sBuild Active Architecture Only 为 debug:YES release:NO链接设备:iPhone 6s (arm64架构的设备)编译(command + shift + B,保证Build Active Architecture Only 为 debug:YES 生效)结果:编译失败,因为当前是debug模式,在该模式下Build Active Architecture OnlyYES,表示只编译支持该指令集的动态库,但是由于Architectures和Build Active Architecture Only的交集中并不存在arm64,故三者的交集为空,故编译失败,无法生成动态库。示例3Architectures 为armv7、arm64Valid Architectures 为armv7、armv7s、arm64Build Active Architecture Only 为 debug:NO release:NO链接设备:iPhone 6s (arm64架构的设备)编译(command + shift + B,保证Build Active Architecture Only 为 debug:YES 生效)结果:编译成功,因为当前是debug模式,在该模式下Build Active Architecture OnlyNO,表示可以编译的结果可能为当前连接的设备所支持的指令集以及其向下兼容的指令集(armv64、armv7s、armv7),其和另外两个编译选项的交集为armv7,故所生成的动态库支持的指令集为armv7

⑤ 制作支持各机型的动态库

  • 支持 iPhone 4 及以后机型的动态库的意思是:生成的动态库支持的指令集为 armv7、armv7s、arm64,因此 Architectures 的三个指令可以设置为:
    • Build Active Architecture Only 统一为 NO;
    • Architectures 和 Valid Architectures 都设置为 armv7、armv7s、arm64、arm64e;
    • 真机 Command + B 则生成支持 armv7、armv7s、arm64 的动态库,模拟器运行则生成支持 i386、x86_64 的动态库。
  • 合并模拟器和真机动态库:使用 lipo -create -output 命令合动态库,注意路径是文件路径,不是 .framework 的路径,如下所示:
    lipo -create /Users/ydw/Library/Developer/Xcode/DerivedData/MyDynamicFramework-cnfmjshbkauwwshdqagjwrgypile/Build/Products/Debug-iphoneos/MyDynamicFramework.framework/MyDynamicFramework /Users/ydw/Library/Developer/Xcode/DerivedData/MyDynamicFramework-cnfmjshbkauwwshdqagjwrgypile/Build/Products/Debug-iphonesimulator/MyDynamicFramework.framework/MyDynamicFramework -output MyDynamic
  • 使用脚本合并:
    • 新建一个 target 脚本:

  • 粘贴脚本到指定位置:


  • 脚本具体内容如下:
   if [ "${ACTION}" = "build" ]thenINSTALL_DIR=${SRCROOT}/Products/${PROJECT_NAME}.frameworkDEVICE_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.frameworkSIMULATOR_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.frameworkif [ -d "${INSTALL_DIR}" ]thenrm -rf "${INSTALL_DIR}"fimkdir -p "${INSTALL_DIR}"cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/"#ditto "${DEVICE_DIR}/Headers" "${INSTALL_DIR}/Headers"# 使用lipo命令将其合并成一个通用framework  # 最后将生成的通用framework放置在工程根目录下新建的Products目录下  lipo -create "${DEVICE_DIR}/${PROJECT_NAME}" "${SIMULATOR_DIR}/${PROJECT_NAME}" -output "${INSTALL_DIR}/${PROJECT_NAME}"#open "${DEVICE_DIR}"#open "${SRCROOT}/Products"fi
  • 编译新 target,编译完成后生成的 framework 位于工程源代码根目录下的 Products 文件夹下面,通过 lipo -info 可以看到动态库已经支持 i386、x86_64、armv7、armv7s、arm64(注意:是工程目录,不是沙盒目录)。

    lipo -info /Users/ydw/Desktop/MyDynamicFramework/Products/MyDynamicFramework.framework/MyDynamicFrameworkArchitectures in the fat file: /Users/ydw/Desktop/Products/MyDynamicFramework.framework/MyDynamicFramework are: i386 x86_64 armv7 arm64
  • 使用动态库:在新工程的 target -> General -> Embedded Binaries 中添加 MyDynamicFramework.framework。

二、动态库的使用

  • 将上文中生成的动态库拖入新工程中,在新工程的 AppDelegate.m 中键入如下代码:
#import <MyDynamicFramework/MyDynamicFramework.h>@interface AppDelegate ()
@end@implementation AppDelegate- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {ViewController *vc = [[ViewController alloc] init];self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];[self.window makeKeyAndVisible];self.window.backgroundColor = [UIColor whiteColor];self.window.rootViewController = vc;[Person logMessage:@"framework test"];return YES;
}
  • 别使用真机和模拟器运行新工程,执行成功,控制台输出如下:
+ [Person logMessage:] -framework test
UByjBj: 2021-08-28 12:39:52 +0000
AORja]: 2021-08-28 12:39:54 +0000

① 使用别人提供的动态库遇到的坑

  • 提供的第三方库所支持的 CPU 指令集不全,出现的错误信息,类似如下图:

  • 这里连接的设备是 iPhone 7 模拟器,其 CPU 架构为 x86_64,但是导入的 framework 是真机编译出来的动态库(支持的指令集为 armv7、armv7s、arm64,并没有 x86_64),所以就报了这样的类似的错误,进一步可以使用上文中的“编译动态库”查看别人提供的动态库所支持的指令集,找出对应的动态库,处理解决即可。
  • 运行过程中出现 image not found 异常或者控制台没有异常输出。原因:没有往 Embedded Binaries 中添加 xxx.framework。

② 动态库动态更新问题

  • 能否用动态库来动态更新 App Store 上的版本呢?
  • framework 本来是苹果专属的内部提供的动态库文件格式,但是自从 2014 年 WWDC 之后,开发者也可以自定义创建 framework 实现动态更新(绕过 App Store 审核,从服务器发布更新版本)的功能,这与苹果限定的上架的 app 必须经过 App Store 的审核制度是冲突的,所以含有自定义的 framework 的 app 是无法在商店上架的,但是如果开发的是企业内部应用,就可以考虑尝试使用动态更新技术来将多个独立的 app 或者功能模块集成在一个 app 上面。
  • 企业内部使用的 app,将企业官网中的板块开发成 4 个独立的 app,然后将其改造为 framework 文件最终集成在一款平台级的 app 当中进行使用,这样就可以在一款 app 上面使用原本 4 个 app 的全部功能。
  • 使用自定义的动态库的方式来动态更新只能用在 in house(企业发布)和 develop 模式却但不能在使用到 App Store,因为在上传打包的时候,苹果会对我们的代码进行一次 Code Singing,包括 app 可执行文件和所有 Embedded 的动态库。因此,只要你修改了某个动态库的代码,并重新签名,那么 MD5 的哈希值就会不一样,在加载动态库的时候,苹果会检验这个 hash 值,当苹果监测到这个动态库非法时,就会造成 Crash。

③ iOS 如何使用 framework 来进行动态更新?

  • 目前 iOS 上的动态更新方案主要有以下四种:
    • HTML 5
    • lua(wax)hotpatch
    • react native
    • framework
  • 前面三种都是通过在应用内搭建一个运行环境来实现动态更新(HTML 5 是原生支持),在用户体验、与系统交互上有一定的限制,对开发者的要求也更高(至少得熟悉 lua 或者 js)。
  • 使用 framework 的方式来更新可以不依赖第三方库,使用原生的 OC/Swift 来开发,体验更好,开发成本也更低。
  • 由于 Apple 不希望开发者绕过 App Store 来更新 app,因此只有对于不需要上架的应用,才能以 framework 的方式实现 app 的更新。
  • 主要思路:将 app 中的某个模块(比如一个 tab)的内容独立成一个 framework 的形式动态加载,在 app 的 main bundle 中,当 app 启动时从服务器上下载新版本的 framework 并加载即可达到动态更新的目的。
  • 创建一个普通工程 DynamicUpdateDemo,其包含一个 framework 子工程 Module。也可以将 Module 创建为独立的工程,创建工程的过程不再赘述。
  • 依赖:在主工程的 Build Phases > Target Dependencies 中添加 Module,并且添加一个 New Copy Files Phase,这样打包时会将生成的 Module.framework 添加到 main bundle 的根目录下。如下所示:

  • 加载
    • 加载的主要代码如下:
   - (UIViewController *)loadFrameworkNamed:(NSString *)bundleName {NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);NSString *documentDirectory = nil;if ([paths count] != 0) {documentDirectory = [paths objectAtIndex:0];}NSFileManager *manager = [NSFileManager defaultManager];NSString *bundlePath = [documentDirectory stringByAppendingPathComponent:[bundleName stringByAppendingString:@".framework"]];// Check if new bundle existsif (![manager fileExistsAtPath:bundlePath]) {NSLog(@"No framework update");bundlePath = [[NSBundle mainBundle]pathForResource:bundleName ofType:@"framework"];// Check if default bundle existsif (![manager fileExistsAtPath:bundlePath]) {UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Oooops" message:@"Framework not found" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];[alertView show];return nil;}}// Load bundleNSError *error = nil;NSBundle *frameworkBundle = [NSBundle bundleWithPath:bundlePath];if (frameworkBundle && [frameworkBundle loadAndReturnError:&error]) {NSLog(@"Load framework successfully");}else {NSLog(@"Failed to load framework with err: %@",error);return nil;}// Load classClass PublicAPIClass = NSClassFromString(@"PublicAPI");if (!PublicAPIClass) {NSLog(@"Unable to load class");return nil;}NSObject *publicAPIObject = [PublicAPIClass new];return [publicAPIObject performSelector:@selector(mainViewController)];}
    • 代码先尝试在 Document 目录下寻找更新后的 framework,如果没有找到,再在 main bundle 中寻找默认的 framework。其中的关键是利用 OC 的动态特性 NSClassFromString 和 performSelector 加载 framework 的类并且执行其方法。
  • 第三方库
   Class XXX is implemented in both XXX and XXX. One of the two will be used. Which one is undefined.
    • 这是当 framework 工程和 host 工程链接了相同的第三方库或者类造成的。为了让打出的 framework 中不包含 host 工程中已包含的三方库(如 cocoapods 工程编译出的 .a 文件),可以这样:
    • 删除 Build Phases > Link Binary With Libraries 中的内容(如有)。此时编译会提示三方库中包含的符号找不到;
    • 在 framework 的 Build Settings > Other Linker Flags 添加 -undefined dynamic_lookup。必须保证 host 工程编译出的二进制文件中包含这些符号。
  • 类文件
    • 尝试过在 framework 中引用 host 工程中已有的文件,通过 Build Settings > Header Search Paths 中添加相应的目录,Xcode 在编译的时候可以成功(因为添加了 -undefined dynamic_lookup),并且 Debug 版本是可以正常运行的,但是 Release 版本动态加载时会提示找不到符号:
   Error Domain=NSCocoaErrorDomain Code=3588 "The bundle “YourFramework” couldn’t be loaded." (dlopen(/var/mobile/Containers/Bundle/Application/5691FB75-408A-4D9A-9347-BC7B90D343C1/YourApp.app/YourFramework.framework/YourFramework, 265): Symbol not found: _OBJC_CLASS_$_BorderedViewReferenced from: /var/mobile/Containers/Bundle/Application/5691FB75-408A-4D9A-9347-BC7B90D343C1/YourApp.app/YourFramework.framework/YourFrameworkExpected in: flat namespacein /var/mobile/Containers/Bundle/Application/5691FB75-408A-4D9A-9347-BC7B90D343C1/YourApp.app/YourFramework.framework/YourFramework) UserInfo=0x174276900 {NSLocalizedFailureReason=The bundle couldn’t be loaded., NSLocalizedRecoverySuggestion=Try reinstalling the bundle., NSFilePath=/var/mobile/Containers/Bundle/Application/5691FB75-408A-4D9A-9347-BC7B90D343C1/YourApp.app/YourFramework.framework/YourFramework, NSDebugDescription=dlopen(/var/mobile/Containers/Bundle/Application/5691FB75-408A-4D9A-9347-BC7B90D343C1/YourApp.app/YourFramework.framework/YourFramework, 265): Symbol not found: _OBJC_CLASS_$_BorderedViewReferenced from: /var/mobile/Containers/Bundle/Application/5691FB75-408A-4D9A-9347-BC7B90D343C1/YourApp.app/YourFramework.framework/YourFrameworkExpected in: flat namespacein /var/mobile/Containers/Bundle/Application/5691FB75-408A-4D9A-9347-BC7B90D343C1/YourApp.app/YourFramework.framework/YourFramework, NSBundlePath=/var/mobile/Containers/Bundle/Application/5691FB75-408A-4D9A-9
    • 因为 Debug 版本暴露了所有自定义类的符号以便于调试,因此你的 framework 可以找到相应的符号,而 Release 版本则不会。目前能想到的方法只有将相同的文件拷贝一份到 framework 工程里,并且更改类名。
  • 访问 Framework 中的图片
    • 在 storyboard/xib 中可以直接访问图片,代码中访问的方法如下:
   UIImage *image = [UIImage imageNamed:@"YourFramework.framework/imageName"]
  • 注意:使用代码方式访问的图片不可以放在 xcassets 中,否则得到的将是 nil。并且文件名必须以 @2x/@3x 结尾,大小写敏感。因为 imageNamed: 默认在 main bundle 中查找图片。

④ 谈谈 Mach-O

  • 在制作 framework 的时候需要选择这个 Mach-O Type,确定 static、dynamic 类型库。
  • 为 Mach Object 文件格式的缩写,它是一种用于可执行文件,目标代码、动态库、内核转储的文件格式。作为 a.out 格式的替代,Mach-O 提供了更强的扩展性,并提升了符号表中信息的访问速度。

⑤ 自己创建的动态库

  • 自建的动态库和系统的动态库有什么区别呢?我们创建的动态库是在自己应用的 .app 目录里面,只能自己的 App Extension 和 APP 使用,而系统的动态库是在系统目录里面,所有的程序都能使用。
  • 可执行文件和自己创建的动态库位置:一般得到的 iOS 程序包是 .ipa 文件。其实就是一个压缩包,解压缩 .ipa 后里面会有一个 payload 文件夹,文件夹里有一个 .app 文件,右键显示包内容,然后找到一个一般体积最大的、与 .app 同名的文件,那个文件就是可执行文件。


  • 在模拟器上运行的时候用 [[NSBundle mainBundle] bundlePath]; 就能得到 .app 的路径,可执行文件就在 .app 里面。而我们自己创建的动态库就在 .app 目录下的 Framework 文件夹里。

  • 我们可以看一下可执行文件中对动态库的链接地址。用 MachOView 查看可执行文件,其中 @rpth 这个路径表示的位置可以查看 Xcode 中的链接路径问题,而现在表示的其实就是 .app 下的 Framework 文件夹。


  • 如下所示,表示静态库、自建的动态库和系统动态库:

三、常见错误

① Architecture

   dlopen(/path/to/framework, 9): no suitable image found.  Did find:
/path/to/framework: mach-o, but wrong architecture
  • 这是说 framework 不支持当前机器的架构。通过如下指令可以查看 framework 支持的 CPU 架构:
   lipo -info /path/to/MyFramework.framework/MyFramework
  • 碰到这种错误,一般是因为编译 framework 的时候,scheme 选择的是模拟器,应该选择 iOS Device。
  • 此外,如果没有选择 iOS Device,编译完成后,Products 目录下的 .framework 文件名会一直是红色,只有在 Derived Data 目录下才能找到编译生成的 .framework 文件。

② 签名

  • 系统在加载动态库时,会检查 framework 的签名,签名中必须包含 TeamIdentifier 并且 framework 和 host app 的 TeamIdentifier 必须一致。
  • 如果不一致,否则会报下面的错误:
   Error loading /path/to/framework: dlopen(/path/to/framework, 265): no suitable image found. Did find:/path/to/framework: mmap() error 1
  • 此外,如果用来打包的证书是 iOS 8 发布之前生成的,则打出的包验证的时候会没有 TeamIdentifier 这一项。这时在加载 framework 的时候会报下面的错误:
   [deny-mmap] mapped file has no team identifier and is not a platform binary:/private/var/mobile/Containers/Bundle/Application/5D8FB2F7-1083-4564-94B2-0CB7DC75C9D1/YourAppNameHere.app/Frameworks/YourFramework.framework/YourFramework
  • 可以通过 codesign 命令来验证:
   codesign -dv /path/to/YourApp.app
  • 如果证书太旧,输出的结果如下:
   Executable=/path/to/YourApp.app/YourAppIdentifier=com.company.yourappFormat=bundle with Mach-O thin (armv7)CodeDirectory v=20100 size=221748 flags=0x0(none) hashes=11079+5 location=embeddedSignature size=4321Signed Time=20181021日 下午10:18:36Info.plist entries=42TeamIdentifier=not setSealed Resources version=2 rules=12 files=2451Internal requirements count=1 size=188
  • 注意其中的 TeamIdentifier=not set。
  • 采用 swift 加载 libswiftCore.dylib 这个动态库的时候也会遇到这个问题,对此Apple 官方的解释是:
   To correct this problem, you will need to sign your app using code signing certificates with the Subject Organizational Unit (OU) set to your Team ID. All Enterprise and standard iOS developer certificates that are created after iOS 8 was released have the new Team ID field in the proper place to allow Swift language apps to run.If you are an in-house Enterprise developer you will need to be careful that you do not revoke a distribution certificate that was used to sign an app any one of your Enterprise employees is still using as any apps that were signed with that enterprise distribution certificate will stop working immediately.
  • 只能通过重新生成证书来解决这个问题。但是 revoke 旧的证书会使所有用户已经安装的,用该证书打包的 app 无法运行,这该怎么解决呢?
  • 现在企业证书的有效期是三年,当证书过期时,其打包的应用就不能运行,那企业应用怎么来更替证书呢?
  • Apple 为每个账号提供了两个证书,这两个证书可以同时生效,这样在正在使用的证书过期之前,可以使用另外一个证书打包发布,让用户升级到新版本。也就是说,可以使用另外一个证书来打包应用,并且可以覆盖安装使用旧证书打包的应用。详情可以看 Apple 文档:
   You are responsible for managing your team’s certificates and provisioning profiles. Apple Developer Enterprise Program certificates expire after three years and provisioning profiles expire after one year.Before a distribution certificate expires, create an additional distribution certificate, described in Creating Additional Enterprise Distribution Certificates. You cannot renew an expired certificate. Instead, replace the expired certificate with the new certificate, described in Replacing Expired Certificates.If a distribution provisioning profile expires, verify that you have a valid distribution certificate and renew the provisioning profile, described in Renewing Expired Provisioning Profiles.

iOS之深入解析如何构建动态库与framework动态更新相关推荐

  1. iOS之深入解析如何构建静态库

    一..a 文件静态库打包 ① 打开 Xcode 创建一个新的 Static Library 工程,取名 MyStaticLibrary: ② 创建工程完毕后,系统自动创建了一个同名类: 添加一个方法用 ...

  2. mac上用qt调用自己生成的qt动态库,该动态库又依赖第三方库

    qt下依赖于第三方库生成的动态库的调用 概述 基于声网的sdk如何在自己的动态库中使用 使用基于第三方库的动态库 下面看pro文件中的设置 概述 初次使用mac上的qtCreator生成动态库,该动态 ...

  3. 【linux】程序找不到动态库.so的解决办法|查看.so动态库信息|.so动态库加载顺序

    目录 找不到.so解决方法 方法一:添加环境变量 方法二:复制so文件到lib路径 方法三:(推荐)添加ldconfig寻找路径 方法四:在编译目标代码时指定该程序的动态库搜索路径 让程序在本目录找到 ...

  4. 【Android 逆向】逆向修改游戏应用 ( 分析应用结构 | 定位动态库位置 | 定位动态库中的修改点 | 修改动态库 | 重打包 )

    文章目录 一.应用结构分析 二.定位动态库位置 三.定位动态库中的修改点 四.修改动态库 五.重打包 一.应用结构分析 分析上一篇博客 [Android 逆向]逆向修改游戏应用 ( APK 解析工具 ...

  5. 【C 语言】动态库封装与设计 ( 动态库调用环境搭建 | 创建应用 | 拷贝动态库相关文件到源码路径 | 导入头文件 | 配置动态库引用 | 调用动态库中的函数 )

    文章目录 一.在 Visual Studio 2019 中创建 " 控制台应用 " 程序 二.拷贝 xxx.lib.xxx.dll.xxx.h 到源码路径 三.导入 xxx.h 头 ...

  6. 【Android 逆向】Android 中常用的 so 动态库 ( /system/lib/libc.so 动态库 | libc++.so 动态库 | libstdc++.so 动态库 )

    文章目录 一.拷贝并分析 Android 中的 /system/lib/libc.so 动态库 二.拷贝并分析 Android 中的 /system/lib/libc++.so 动态库 三.拷贝并分析 ...

  7. Linux下动态库的创建与更新

    Linux下动态库(libname.x.y.z)的创建与更新 由于主程序和它依赖的共享库是由不同的开发者开发的.共享库的开发者会不停地更新共享库的版本,以修正bug,增加功能或改进性能.版本多了之后, ...

  8. python调用qt动态库_QT开发——动态库(.so文件)的生成与调用

    1.qmake方式生成和调用动态库 链接:https://blog.csdn.net/lywzgzl/article/details/42805991 2.cmake方式生成和调用动态库 2.1创建共 ...

  9. CMake从0到1:Linux编译动态库,调用动态库,VSCode单步执行

    工欲善其事必先利其器,如果要想在Linux系统上编写C++代码,常常我们会有如下几个需求: 1.编译可执行文件 2.可执行文件调用动态库,这里通常包括两种情况:(1)自己的动态库,那就得先生成再链接: ...

最新文章

  1. 中介者模式 调停者 Mediator 行为型 设计模式(二十一)
  2. NTU 课程笔记:MAS 714(16) 图灵机
  3. C语言学习之有一个分数序列2/1、3/2、5/3、8/5、13/8、21/13,……求出这个数列的前20项之和。
  4. python中的构造函数和构造函数和析构函数的作用
  5. js字符串常用判断方法
  6. Eclipse下载及汉化(官方最新)
  7. html 轮播图左右切换代码,js实现左右轮播图
  8. LaTeX2021 公式编写、图文安装、详细教程、一文读懂
  9. vs2019安装时,一直卡在正在提取文件
  10. 传统语音识别介绍【二】—— 特征提取
  11. 蓝桥杯_单片机_入门基础知识(七)_DS18b20
  12. 基于S变换的电压暂降检测研究及仿真设计
  13. C++ STL常用标准库容器入门(vector,map,set,string,list...)
  14. 百度地图api根据地图缩放等级显示不同的marker点,功能二
  15. 牛津博士讲大数据和量化金融
  16. nodejs十六进制转字符串
  17. java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:MaxGCPauseMillis=100/虚拟机调优
  18. win7系统设备管理器打开后一片空白怎么办
  19. 获刑2年半!大学生利用漏洞免费吃肯德基,还把“方法”分享给同学
  20. 【转载】基于rasa的对话系统搭建(下)

热门文章

  1. 英语笔记3(git)
  2. Java_cpu飙升排查
  3. 第十章 优先级队列 (b1)完全二叉堆:结构
  4. springboot13 发布和监听事件
  5. HTML5自定义播放器(简式)
  6. 一个简单的TCP服务器
  7. Java Generics and Collections-2.1
  8. avalon.js实践 svg地图配置工具
  9. 批量处理jdbc语句提高处理速度
  10. python替代技术,Python超级方法和调用替代品