目录
一、理解学习gcc生成静态库与动态库,并使用。
(一)学习过程
1.准备阶段三个代码,将一个.c文件表编译成.o,并查看。
hello.h
#ifndef HELLO_H
#define HELLO_H
void hello(const char *name);
#endif//HELLO_H
hello.c
#include<stdio.h>
void hello(const char *name)
{
printf("Hello %s\n",name);
}
main1.c
#include"hello.h"
int main()
{
hello("everyone");
return 0;
}
用gcc将hello.c编译成.o文件并查看
2.静态库的使用
创建一个静态库
静态库的使用
3.动态库的使用
创建动态库![](https://i-blog.csdnimg.cn/blog_migrate/a9fbcbadcd69dcaf3fa38d07165bc6a1.png)
出现错误,将libmyhello.so复制到目录/usr/lib中。由于运行时,是在/usr/lib中找库文件的。
(二)实际应用1
1.代码
A1.c
#include<stdio.h>
void print1(int arg)
{
printf("A1 print arg:%d\n",arg);
}
A2.c
#include<stdio.h>
void print2(char *arg)
{
printf("A2 printf arg:%s\n",arg);
}
A.h
#ifndef A_H
#define A_H
void print1(int);
void print2(char *);
#endif
test.c
#include<stdio.h>
#include"A.h"
int main()
{
print1(1);
print2("test");
return 0;
}
ar crv libfile.a A1.o A2.o
gcc -o test test.c libfile.a
gcc -shared -fPIC -o libfile.so A1.o A2.o
gcc -o test test.c libfile.so
sudo mv libfile.so /usr/lib
(三)实际应用2
创建三个文件,然后编译成.o文件
main.c
#include <stdio.h>
#include "sub1.c"
#include "sub2.c"
int main()
{
int a,b;
a=8;b=2;
float c,d;
c=x2x(a,b);
d=y2y(c);
printf("%f\n",d);
return 0;
}
sub1.c
#include<stdio.h>
float x2x(int a,int b)
{
float c;
c=a/b;
return c;
}
sub2.c
#include<stdio.h>
float y2y(float c)
{
float d;
d=c+1;
return d;
}
gcc -c sub1.c sub2.c
ar crv libsub.a sub1.o sub2.o
gcc main.c libsub.a -o main
gcc -shared -fPIC libsub.so sub1.o sub2.o
gcc -o main main.c libsub.so
sudo mv libsub.so /usr/lib
二、gcc深入学习
(一)gcc常用命令
1.写出一段代码,并编译
test.c
#include<stdio.h>
int main(void)
{
printf("Hello World!\n");
return 0;
}
gcc test.c -o test
预编译
gcc -E test.c -o test.i
编译为汇编代码
gcc -S test.i -o test.s
gcc -c test.s -o test.o
gcc test.o -o test
2.检错
gcc -pedantic test.c -o test1
-pedantic:帮助发现一些不符合ANSI/ISO C标准的代码,当出现不符合的代码,会发出警告信息
gcc -Wall test.c -o test2
-Wall:帮助发现一些不符合ANSI/ISO C标准的代码,当出现不符合的代码,gcc会发出尽可能多的警告信息
gcc -Werror test.c -o test3
-Werror:gcc会在所有产生警告的地方停止编译,迫使进行代码的修改
3.库函数连接
库文件:动态链接库(.so),静态链接库(.a)
函数库:头文件(.h),库文件(.so)
注意:头文件一般放在/usr/include目录下,库文件一般放在/usr/lib目录下
①编译
gcc -c -I /usr/include 源文件 -o 生成.o文件
②链接
gcc -L /usr/lib 动态链接库文件名 生成.o文件 -o 生成可执行文件
③强制性使用静态链接库
gcc链接时会优先使用动态链接库,想强制使用静态链接库执行在命令中加-static
gcc -L /usr/lib -static 静态链接库文件名 生成.o文件 -o 生成可执行文件
静态链接时搜索路径顺序:
a、ld会去找gcc命令中的参数-L
b、gcc的环境变量LBRARY_PATH(指定程序静态链接库文件的搜索路径)
c、内定目录/lib /usr/lib /usr/local/lib
动态链接时搜索路径顺序:
a、编译目标代码时指定的动态库搜索路径
b、环境变量LD_LIBRARY_PATH(指定程序动态链接库文件的搜索路径)
c、配置文件/etc/ld.so.conf中指定的动态库搜索路径
d、默认的动态库搜索路径/lib
e、默认的动态库搜索路径/usr/lib
(二)gcc的合作伙伴
- addr21line
帮助调试器在调试过程中定位对应的源代码。 - ar
用于创建静态链接库。 - ld
用于链接。 - as
用于汇编。 - ldd
查看执行文件所用到的链接库。 - size
查看执行文件中各部分的大小。 - readelf
查看ELF各个部分的内容。 - objdump
进行反汇编。
(三)nasm编译
1.安装
nasm -f elf hello.asm,会生成一个hello.o文件
三、opencv的学习
安装自行解决
(一)图片
创建一个文件夹
nano test1.cpp
test1.cpp
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
CvPoint center;
double scale = -3;
IplImage* image = cvLoadImage("lena.jpg");
argc == 2? cvLoadImage(argv[1]) : 0;
cvShowImage("Image", image);
if (!image) return -1; center = cvPoint(image->width / 2, image->height / 2);
for (int i = 0;i<image->height;i++)
for (int j = 0;j<image->width;j++) {
double dx = (double)(j - center.x) / center.x;
double dy = (double)(i - center.y) / center.y;
double weight = exp((dx*dx + dy*dy)*scale);
uchar* ptr = &CV_IMAGE_ELEM(image, uchar, i, j * 3);
ptr[0] = cvRound(ptr[0] * weight);
ptr[1] = cvRound(ptr[1] * weight);
ptr[2] = cvRound(ptr[2] * weight);
}
Mat src;Mat dst;
src = cvarrToMat(image);
cv::imwrite("test.png", src);
cvNamedWindow("test",1); imshow("test", src);
cvWaitKey();
return 0;
}
g++ test1.cpp -o test1 `pkg-config --cflags --libs opencv`
./test1
(二)视频
1.打开摄像头
点击 “ 虚拟机 ” ,然后点击 “ 设置(S)… ”。
选择 “ USB控制器 ” ,将 “ USB兼容性 ” 设置为 “ USB 3.0 ” ,并点击确定。
选择 “ 虚拟机 ” ,再选择 “ 可移动设备 ” ,再选择 “ Quanta USB2.0 VGA UVC WebCam ” ,最后点击 “ 连接 ” ,再弹出的窗口内点击 “ 确定 ” 。
角这个摄像头图标有个小绿点,则连接成功。
2.播放视频
创建一个 test2.cpp 文件。
nano test2.cpp
#include <opencv2/opencv.hpp>
using namespace cv;
int main()
{
//从摄像头读取视频
VideoCapture capture("man.mp4");
//循环显示每一帧
while(1){
Mat frame;//定义一个Mat变量,用于存储每一帧的图像
capture >> frame;//读取当前帧
if(frame.empty())//播放完毕,退出
break;
imshow("读取视频帧",frame);//显示当前帧
waitKey(30);//掩饰30ms
}
system("pause");
return 0;
}
g++ test2.cpp -o test2 `pkg-config --cflags --libs opencv`
四、总结
这次学习内容比较多,但是收获也比较多,虽然艰辛,但是硕果累累。 借鉴了几位大佬的博客,可以去学习学习。