python静态编译成动态库_关于静态库动态库的经验总结

本文深入探讨了静态库与动态库的区别,揭示了静态库如何在编译时不进行链接,以及为何在使用第三方静态库时需要显式指定依赖。对比了动态库的链接机制,并讨论了CocoaPods和Carthage在依赖管理中的差异,以及它们如何适应iOS历史变迁中的库形式变化。
摘要由CSDN通过智能技术生成

最近整理一些项目以前依赖留下的问题,在使用 CocoaPods 和 Carthage 的时候引出了关于静态库和动态库的思考,手动编译静态库的朋友应该知道,如果自己编译了一个静态库,这个静态库依赖了 iOS 自带的库,即使你在Xcode开发工具http://www.maiziedu.com/course/234/中显式指定了依赖,当你在另一个工程中使用这个静态库的时候,依旧需要显式在那个工程指定这个静态库所依赖的系统库。

举个栗子

AFNetworking 是个好东西,大家都喜欢用,在日常使用的时候,一般都是使用 CocoaPods 引入这个库,笔者前面有篇文章分析了 CocoaPods 做了什么工作,但是却没有分析 CocoaPods 为何如此设计,这里先卖个关子不讲。AFNetworking 依赖Security.framework MobileCoreServices.frameworkSystemConfiguration.framework 三个系统框架,如果我们将其编译为静态库,然后这个静态库被其他工程依赖,那么其他工程依旧需要引入这三个框架。如果我们将其编译为动态库,则不需要依赖这三个框架。这个情况引起了笔者的兴趣

分析

既然问题是编译链接,那么就需要从动态库和静态库入手分析,首先,我们需要明确的是,系统提供的 framework 都是动态库的形式提供的。这很好理解,因为 UIKit 这类 framework 被使用的太频繁了,内存中完全只需要保留一份副本。这样也能减轻 App 的大小。那么直接来着手模拟一下其编译过程。

模拟静态库的编译

创建一个动态库用于模拟系统库

dynamic.h

----------void hello();

dynamic.c

----------#include "dynamic.h"#include

void hello() {

printf("Hello World");

}

然后编译打包动态库

> gcc -c -o dynamic.o dynamic.c # 编译为对象文件

> gcc -shared dynamic.o -o libdynamic.so

创建一个静态库用于模拟第三方静态库

static.h

--------void sayHello();

static.c

--------#include "static.h"#include "dynamic.h"

void sayHello() {

hello();

}

然后编译静态库

> gcc -c -o static.o static.c

> ar -r libstatic.a static.o

这里大家有没有发现一个问题,静态库实际上并没有链接动态库,仅仅只是 include 了一个头文件用于编译通过。最终生成的静态库根本不知道动态库的存在。然后创建一个带有main 函数的程序

hello.c

-------#include "static.h"int main(int argc, char *argv[]) {

sayHello();

}

然后编译

> gcc -o hello hello.c -L. -lstatic# 直接报错没有找到 hello() 的二进制代码

Undefined symbols for architecture x86_64:

"_hello", referenced from:

_sayHello in libstatic.a(static.o)

ld: symbol(s) not found for architecture x86_64

clang: error: linker command failed with exit code 1 (use -v to see invocation)

模拟动态库的编译

创建一个动态库用于模拟系统库

dynamic1.h

----------void hello();

dynamic1.c

----------#include "dynamic1.h"#include

void hello() {

printf("Hello World");

}

然后编译打包动态库

> gcc -c -o dynamic1.o dynamic1.c # 编译为对象文件

> gcc -shared dynamic1.o -o libdynamic1.so

创建动态库用于模拟第三方动态库

dynamic2.h

--------void sayHello();

dynamic2.c

--------#include "dynamic2.h"#include "dynamic1.h"

void sayHello() {

hello();

}

然后编译打包动态库

> gcc -c -o dynamic2.o dynamic2.c # 编译为对象文件

> gcc -shared dynamic2.o -o libdynamic2.so# 报错,显示 dynamic2.o 中没有 hello() 二进制代码

Undefined symbols for architecture x86_64:

"_hello", referenced from:

_sayHello in dynamic2.o

ld: symbol(s) not found for architecture x86_64

clang: error: linker command failed with exit code 1 (use -v to see invocation)

> gcc -shared dynamic2.o -o libdynamic2.so -L. -ldynamic1# 成功,无报错

然后创建一个带有 main 函数的程序

hello.c

-------#include "static.h"int main(int argc, char *argv[]) {

sayHello();

}

然后编译

> gcc -o hello hello.c -L. -ldynamic2

总结

从上面两个编译过程大家应该也能明白了,静态库实际上只是对象文件的打包,也就是说,只经过了编译过程,而没有链接过程,编译一个静态库甚至只需要满足所有函数的声明就行,而动态库虽然没有经过正规的链接,但是实际上还是通过 gcc 做了跟其他动态库的链接,动态库自身有了依赖的概念。所以不需要在工程中显式依赖了。这里可能有朋友想要问,这种知识有什么用处?实际上这种知识在依赖管理中有用,前面说过 CocoaPods 对工程修改了很多内容,这是有原因的,因为 iOS8 之前是不存在动态库的,只存在静态库,CocoaPods 不得不对目标工程也作出修改来添加对其他库的依赖,因为静态库不知道自身依赖什么库。而 Carthage 则只支持 iOS8 和动态库,所以完全可以没有侵入性,只需要提供一个动态库,然后工程依赖这个动态库就行了。

原文来自:推酷

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当我们需要在Python中调用C++程序时,我们通常会选择将C++程序编译成动态库(.dll或.so文件),然后在Python中引用它。下面是一些步骤: 1.编写C++程序并将其编译动态库,例如Windows平台上的.dll文件或Linux平台上的.so文件。 2.使用Python中的ctypes模块来加载动态库,并调用其中定义的函数。这个过程需要知道动态库中函数的名称和参数类型。 3.在Python中调用动态库中的函数,获取返回值并进行处理。 以下是一个简单的示例代码: 假设我们有一个C++程序,包含一个名为add_numbers的函数,它接受两个整数并返回它们的和。 ```c++ // add_numbers.cpp #include "add_numbers.h" int add_numbers(int x, int y) { return x + y; } ``` 我们可以将其编译为Windows平台上的.dll文件,使用以下命令: ``` g++ -shared -o add_numbers.dll add_numbers.cpp ``` 在Python中,我们可以使用以下代码来加载动态库,并调用其中的函数: ```python import ctypes # 加载动态库 add_numbers_lib = ctypes.WinDLL('add_numbers.dll') # 获取函数 add_numbers = add_numbers_lib.add_numbers # 设置参数类型 add_numbers.argtypes = [ctypes.c_int, ctypes.c_int] # 设置返回值类型 add_numbers.restype = ctypes.c_int # 调用函数 result = add_numbers(1, 2) print(result) # 输出3 ``` 相关问题: 1. C++程序编译成动态库有哪些优点? 2. Python如何加载动态库? 3. 如何在Python中调用动态库中的函数?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值