Unix下设计动态库的方法《精通Unix下C语言编程与项目实践》(一)

简介:

  精通Unix下C语言编程与项目实践

之动态库的生成

作者:朱云翔,胡平 

3.3 动态库的生成

动态库的生成可分为三个步骤,设计库源码、编译位置无关码(PIC)型.o文件和链接动态库。链接动态库的命令包含特殊标志,与链接静态库和链接可执行目标文件有区别,而且不同的Unix系统,其实现的细节也不尽相同。
编译PIC.o中间文件的方法一般是采用C语言编译器的“-KPIC”或者“-fpic”选项,有的Unix版本C语言编译器缺省带上了PIC标志。创建最终动态库的方法一般是采用C语言编译器的“-G”或者“-shared”选项,或者直接使用工具ld创建。
本处设计一个创建并调用动态库的例子,分别将源文件d1.cd2.c编译为动态库d1.sod2.so,并在主程序中调用之。

1. 设计库源码

程序pr1.c提供了函数print和变量p,如代码3-4所示:
代码3-4 动态库源码(节自/code/chapter3/d1.c
int p = 2;
void print()
{
        printf("This is the first dll src!\n");
}
程序pr2.c也提供了自己的函数print和变量p,如代码3-5所示:
代码3-5 动态库源码(节自/code/chapter3/d2.c
int p = 3;
void print()
{
        printf("This is the second dll src!\n");
}

2. ScoSolaris系列

    通过cc的“-KPIC”选项生成PIC中间文件,再通过cc的“-G”选项链接成动态库:
cc –O -KPIC -c d1.c d2.c    /*  编译以“ .o ”为扩展名的中间目标文件 d1.o d2.o */
cc -G -o d1.so d1.o     /*  根据中间目标文件 d1.o 创建动态库文件 d1.so */
cc -G -o d2.so d2.o     /*  根据中间目标文件 d2.o 创建动态库文件 d2.so */
或者直接一步到位,直接创建动态库文件d1.sod2.so
cc -O -KPIC -G -o d1.so d1.c                    /*  创建动态库文件 d1.so */
cc -O -KPIC -G -o d2.so d2.c                    /*  创建动态库文件 d2.so */

3. HP-UNIX系列

创建 PIC 中间文件的编译器选项是+z,创建动态库的链接器标志是-b
cc +z -c d1.c d2.c      /*  编译以“ .o ”为扩展名的中间目标文件 d1.o d2.o */
ld -b -o d1.so d1.o     /*  根据中间目标文件 d1.o 创建动态库文件 d1.so */
ld -b -o d2.so d2.o     /*  根据中间目标文件 d2.o 创建动态库文件 d2.so */
与大部分系统不同的是,HP-UNIX缺省使用“.sl”做动态库的扩展名。

4. AIX系列

AIX中,ccxlc系列都是C语言编译器。
xlc_r4 -c d1.c d2.c     /*  编译以“ .o ”为扩展名的中间目标文件 d1.o d2.o */
ld -G -bnoentry -bexpall -lc d1.o -o d1.so  /*  创建动态库文件 d1.so */
ld -G -bnoentry -bexpall -lc d2.o -o d2.so  /*  创建动态库文件 d2.so */
ld是创建动态库的工具,它的常用选项与cc类似,比如“-l”标识链接库,“-o”标识目标文件名称等。本处“-G”选项等价于指定带有-b标记的 erokrtlnortllibnosymbolicnoautoexp  M:SRE选项,它将创建动态库对象。更多的ld信息请参考相关文档。

5. Linux和其他使用gcc编译器的Unix

gcc -fpic -c d1.c d2.c  /*  编译以“ .o ”为扩展名的中间目标文件 d1.o d2.o */
gcc -shared -o d1.so d1.o   /*  根据中间目标文件 d1.o 创建动态库文件 d1.so */
gcc -shared -o d2.so d2.o   /*  根据中间目标文件 d2.o 创建动态库文件 d2.so */
或者直接一步到位:
gcc -O -fpic -shared -o d1.so d1.c          /*  创建动态库文件 d1.so */
gcc -O -fpic -shared -o d2.so d2.c          /*  创建动态库文件 d2.so */
某些版本的gcc上也可以使用“-G”替换“-shared 选项。



 本文转自 zhuyunxiang 51CTO博客,原文链接:http://blog.51cto.com/zhuyunxiang/128695,如需转载请自行联系原作者



相关文章
|
Unix Shell API
组合思维:Unix 哲学到底给现代编程带来哪些重要启示?
Unix哲学提供了一套简洁而强大的设计理念,这些理念在现代编程中依然具有重要的指导意义。通过模块化设计、组合工具、避免过早优化以及注重可复用性和可扩展性,开发者可以构建出更高效、更健壮的软件系统。希望本文能够帮助读者深入理解Unix哲学,并在实际开发中应用这些宝贵的设计原则。
469 25
|
存储 编译器 C语言
【C语言】数据类型全解析:编程效率提升的秘诀
在C语言中,合理选择和使用数据类型是编程的关键。通过深入理解基本数据类型和派生数据类型,掌握类型限定符和扩展技巧,可以编写出高效、稳定、可维护的代码。无论是在普通应用还是嵌入式系统中,数据类型的合理使用都能显著提升程序的性能和可靠性。
754 8
|
传感器 人工智能 物联网
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发,以及面临的挑战和未来趋势,旨在帮助读者深入了解并掌握这些关键技术。
510 6
|
C语言 开发者
C语言中的模块化编程思想,介绍了模块化编程的概念、实现方式及其优势,强调了合理划分模块、明确接口、保持独立性和内聚性的实践技巧
本文深入探讨了C语言中的模块化编程思想,介绍了模块化编程的概念、实现方式及其优势,强调了合理划分模块、明确接口、保持独立性和内聚性的实践技巧,并通过案例分析展示了其应用,展望了未来的发展趋势,旨在帮助读者提升程序质量和开发效率。
904 5
|
C语言
C语言编程中,错误处理至关重要,能提升程序的健壮性和可靠性
C语言编程中,错误处理至关重要,能提升程序的健壮性和可靠性。本文探讨了C语言中的错误类型(如语法错误、运行时错误)、基本处理方法(如返回值、全局变量、自定义异常处理)、常见策略(如检查返回值、设置标志位、记录错误信息)及错误处理函数(如perror、strerror)。强调了不忽略错误、保持处理一致性及避免过度处理的重要性,并通过文件操作和网络编程实例展示了错误处理的应用。
550 4
|
存储 算法 Linux
C语言 多进程编程(一)进程创建
本文详细介绍了Linux系统中的进程管理。首先,文章解释了进程的概念及其特点,强调了进程作为操作系统中独立可调度实体的重要性。文章还深入讲解了Linux下的进程管理,包括如何获取进程ID、进程地址空间、虚拟地址与物理地址的区别,以及进程状态管理和优先级设置等内容。此外,还介绍了常用进程管理命令如`ps`、`top`、`pstree`和`kill`的使用方法。最后,文章讨论了进程的创建、退出和等待机制,并展示了如何通过`fork()`、`exec`家族函数以及`wait()`和`waitpid()`函数来管理和控制进程。此外,还介绍了守护进程的创建方法。
C语言 多进程编程(一)进程创建
|
NoSQL C语言 索引
十二个C语言新手编程时常犯的错误及解决方式
C语言初学者常遇错误包括语法错误、未初始化变量、数组越界、指针错误、函数声明与定义不匹配、忘记包含头文件、格式化字符串错误、忘记返回值、内存泄漏、逻辑错误、字符串未正确终止及递归无退出条件。解决方法涉及仔细检查代码、初始化变量、确保索引有效、正确使用指针与格式化字符串、包含必要头文件、使用调试工具跟踪逻辑、避免内存泄漏及确保递归有基准情况。利用调试器、编写注释及查阅资料也有助于提高编程效率。避免这些错误可使代码更稳定、高效。
2457 12
|
Java 编译器 C语言
【一步一步了解Java系列】:Java中的方法对标C语言中的函数
【一步一步了解Java系列】:Java中的方法对标C语言中的函数
269 3
|
算法 Unix 数据安全/隐私保护
Python编程--UNIX口令破解机
Python编程--UNIX口令破解机
277 1
|
Linux C语言
C语言 多进程编程(三)信号处理方式和自定义处理函数
本文详细介绍了Linux系统中进程间通信的关键机制——信号。首先解释了信号作为一种异步通知机制的特点及其主要来源,接着列举了常见的信号类型及其定义。文章进一步探讨了信号的处理流程和Linux中处理信号的方式,包括忽略信号、捕捉信号以及执行默认操作。此外,通过具体示例演示了如何创建子进程并通过信号进行控制。最后,讲解了如何通过`signal`函数自定义信号处理函数,并提供了完整的示例代码,展示了父子进程之间通过信号进行通信的过程。