当代码版本接口已经稳定,希望约束调用方式,或者不希望代码功能被随便修改,或者有知识产权/核心算法保护诉求,或者希望统一版本,避免“他们改了一版源码自己跑飞了”的时候,这个时候我们可以将代码编译成库文件封装好后进行交付。目标:在Linux中将C/C++代码编译成.a或者.so的库文件,在demo中调用。以一个简单的函数为例子,提供一个 add(a, b),返回 a + b,演示怎么封装成库。照着这个做完,后面换成自己写的代码是同一套逻辑。封装好函数内部的代码。最终想做到业务侧代码只需要这样写,然后链接库,就能跑:#include<iostream>#include"mylib.h"intmain(){int c = add(3, 5);std::cout << "result = " << c << std::endl;return0;}
demo_sdk/├── include/│ └── mylib.h├── src/│ └── mylib.cpp├── demo/│ └── main.cpp└── CMakeLists.txt
#ifndef MYLIB_H#define MYLIB_H#ifdef __cplusplusextern"C" {#endifintadd(int a, int b);#ifdef __cplusplus}#endif#endif
这个头文件是对外接口。这样写的好处是?内部虽然是 C++,但这样导出的接口更稳,尤其后面如果:给 C 调用、给不同编译器环境调用、想减少名字修饰问题,会更省事。#include"mylib.h"intadd(int a, int b){return a + b;}
#include<iostream>#include"mylib.h"intmain(){int result = add(10, 20);std::cout << "10 + 20 = " << result << std::endl;return0;}
cmake_minimum_required(VERSION 3.10)project(demo_sdk)set(CMAKE_CXX_STANDARD 11)set(CMAKE_CXX_STANDARD_REQUIRED ON)# 头文件目录include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)# 生成静态库 libmylib.aadd_library(mylib STATIC src/mylib.cpp)# 生成静态库 libmylib.so# add_library(mylib SHARED# src/mylib.cpp# )# 生成可执行文件add_executable(main_demo demo/main.cpp)# 把库链接给 demotarget_link_libraries(main_demo mylib)
mkdir -p buildcd buildcmake ..make
执行完以上命令后会在build文件夹下生成库文件,有.a静态库文件,和.so动态库文件在Bash里输入./main_demo命令,可以运行我们写的demo,运行成功后输出10+20=30,完整的Bash命令及输出如下:- main_demo:调用方只通过头文件和库使用功能
调用方不需要再直接编译 mylib.cpp,只需要:sdk_package/├── include/│ └── mylib.h├── lib/│ └── libmylib.a└── demo/ └── main.cpp
- 静态库部署非常简单。只需要一个可执行程序,例如:main_demo直接运行。
- 必须保证:libxxx.so 在系统能找到的路径,否则:会报错 error while loading shared libraries
- 因此需要需要配置:LD_LIBRARY_PATH 或者:/usr/lib, /usr/local/lib
- 动态库升级只需要替换:libxxx.so,程序不用重新编译。
① 部署简单。嵌入式设备可能:文件系统小,没有标准库路径。不方便设置 LD_LIBRARY_PATH。静态库就不会有这些问题。② 依赖更少。动态库可能依赖:glibc;libstdc++;libpthread;嵌入式环境经常版本不一致。③ 稳定性更高。动态库容易出现:ABI 不兼容,比如:gcc 版本不同