目录
一、gcc 生成 .a 静态库和 .so 动态库
1.创建作业目录
(1)创建test1目录
(2)进入test1目录
2.用vim编写hello.h、hello.c和main.c文件
程序1 hello.h
#ifndef HELLO_H
#define HELLO_H
void hello(const char *name);
#endif //HELLO_H
程序2 hello.c
#include <stdio.h>
void hello(const char *name)
{
printf("Hello %s!\n", name);
}
程序3 main.c
#include "hello.h"
int main()
{
hello("everyone");
return 0;
}
3.将 hello.c 编译成.o 文件
用ls命令查看是否生成
4.由.o文件创建静态库
用ls命令查看是否生成
5.程序中使用静态库
下面先生成目标程序 hello,然后运行 hello 程序看看结果如何。
运行hello文件
删除静态库文件试试公用函数 hello 是否真的连接到目标文件 hello 中了
程序照常运行,静态库中的公用函数已经连接到目标文件中了
6.由.o 文件创建动态库文件
动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀 lib,但其文件扩展名为.so
7.在程序中使用动态库
在程序中使用动态库和使用静态库完全一样,也是在使用到这些公用函数的源程序中包含 这些公用函数的原型声明,然后在用 gcc 命令生成目标文件时指明动态库名进行编译。我 们先运行 gcc 命令生成目标文件,再运行它看看结果。
(或 #gcc main.c libmyhello.so -o hello 不会出错(没有 libmyhello.so 的话,会出错),但是 接下来./hello 会提示出错,因为虽然连接时用的是当前目录的动态库,但是运行时,是到 /usr/lib 中找库文件的,将文件 libmyhello.so 复制到目录/usr/lib 中就 OK 了)
(找不到动态库文件 libmyhello.so。程序在运行时, 会在/usr/lib 和/lib 等目录中查找需要的动态库文件。若找到,则载入动态库,否则将提 示类似上述错误而终止程序运行。)
将文件 libmyhello.so 复制到目录/usr/lib 中,再运行
8.当静态库和动态库同名时,gcc 命令会使用哪个库文件
先删除除.c 和.h 外的所有文件,恢复成我们刚刚编辑完举例程序状态
再来创建静态库文件 libmyhello.a 和动态库文件 libmyhello.so。
(通过上述最后一条 ls 命令,可以发现静态库文件 libmyhello.a 和动态库文件 libmyhello.s o 都已经生成,并都在当前目录中。然后,我们运行 gcc 命令来使用函数库 myhello 生成目 标文件 hello,并运行程序 hello。)
gcc -o hello main.c -L. –lmyhello
(动态库和静态库同时存在时,优先使用动态库,当然,如果直接 #gcc main.c libmyhello.a -o hello 的话,就是指定为静态库了)
./hello
./hello: error while loading shared libraries: libmyhello.so: cannot
open shar ed object file: No such file or directory
从程序 hello 运行的结果中很容易知道,当静态库和动态库同名时,gcc 命令将优先使用动 态库,默认去连/usr/lib 和/lib 等目录中的动态库,将文件 libmyhello.so 复制到目录/usr/lib 中即可。
二、作业一程序基础gcc改编生成静态库和动态库并比较大小
1.用vim编写x2x.c、x2y.c、main.c、main.h。
main.h
#ifndef MAIN
#define MAIN
#include<stdio.h>
float x2x(int x,int y);
float x2y(int x,int y);
#endif
main.c
#include"main.h"
int main()
{
int x=16,y=10;
printf("%f\n",x2x(x,y));
printf("%f\n",x2y(x,y));
return 0;
}
x2x.c
#include"main.h"
float x2x(int a,int b)
{
float sum=a+b;
return sum;
}
x2y.c
#include"main.h"
float x2y(int a,int b)
{
float c=a-b;
return c;
}
2.将x2x.c和x2y.c和main.c编译成.o文件
3.将x2x、x2y目标文件用 ar工具生成1个 .a 静态库文件
4.用 gcc将 main函数的目标文件与此静态库文件进行链接,生成最终的可执行程序,并记录大小
输出结果
静态库大小
5.将x2x、x2y目标文件生成1个 .so 动态库文件
6.用 gcc将 main函数的目标文件与此动态库文件进行链接,生成最终的可执行程序,记录大小并与静态库比较
错误因为找不到动态库文件 libmyhello.so。程序在运行时, 会在/usr/lib 和/lib 等目录中查找需要的动态库文件。我们将文件 libmyhello.so 复制到目录/usr/lib 中,再输出。
动态库大小
比较大小
由此可以看出动态库文件大小要比静态库文件大小大很多。
三、下载安装nasm并用nasm编译生成程序
1.nasm下载安装
输入命令进行下载
sudo apt-get installl nasm
2.“hello.asm”编译生成可执行程序
1.生成文件并写下代码
hello.asm程序代码如下
; hello.asm
section .data ; 数据段声明
msg db "Hello, world!", 0xA ; 要输出的字符串
len equ $ - msg ; 字串长度
section .text ; 代码段声明
global _start ; 指定入口函数
_start: ; 在屏幕上显示一个字符串
mov edx, len ; 参数三:字符串长度
mov ecx, msg ; 参数二:要显示的字符串
mov ebx, 1 ; 参数一:文件描述符(stdout)
mov eax, 4 ; 系统调用号(sys_write)
int 0x80 ; 调用内核功能
; 退出程序
mov ebx, 0 ; 参数一:退出代码
mov eax, 1 ; 系统调用号(sys_exit)
int 0x80 ; 调用内核功能
2.编译生成程序并运行
3.查看程序大小
3.“hello world”C代码的编译生成的程序
1.创建hello.c文件
写下代码
#include<stdio.h>
int void main()
{
printf("Hello World!\n");
return 0;
}
2.编译并输出
3.程序大小为
4.2种程序大小进行比较
从上面可以看出nasm生成的执行程序要比c代码编译生成的程序小得多
四、借助第三方库函数完成代码设计
1.最常用的光标库(curses)的主要函数功能
(1)cbreak():调用cbreak函数后,除了"Del"和"Ctrl"键外,接受其他所有字符输入。
(2)nl (/nonl ):输出时,换行是否作为回车字符。nl函数将换行作为回车符,而nonl函数相反。
(3)noecho()/echo():关闭/打开输入回显功能。
(4)intrflush(WINDOW *win,bool bf) win为标准输出。当bf为true时输入Break,可以加快中断的响应。但是,有可能会造成屏幕输出信息的混乱。
(5)keypad (WINDOW *win, bool bf) : win为标准输出。调用keypad函数后,将可以使用键盘上的一些特殊字符,如方向键,转化成curses.h中的特殊键。
(6)refresh():重绘屏幕显示内容。在调用initscr函数后,第一次调用refresh函数会清除屏幕显示。
2.在Ubuntu中安装curses库
1.使用下面命令安装
2.查找头文件
输入命令
cd /usr/include
3.查找库文件
输入命令
cd /usr/lib
3.以游客身份体验一下即将绝迹的远古时代的 BBS
4.gcc编译生成一个终端游戏
代码编译
cc mysnake1.0.c -lcurses -o mysnake1.0
输出
./mysnake1.0
五、总结
这次的作业学会了用gcc 生成 .a 静态库和 .so 动态库,也在游戏中了解到了curses库灵活链接和使用。