共享库so
2024-10-21 03:05:50
so文件在linux中为共享库,与windows下的dll类似。
so文件中的函数可供多个进程调用,最大可能的提供二进制代码的复用。
共享库可以使代码的维护工作大大简化,当修正了一些错误或者添加了新特性的时候,用户只需要获得升级后的so并安装他就可以。
注:即使不同的进程调用同一个so文件,通过共享库并不能实现不同进程间的通讯,因为同一个so被不同进程加载加载到不同的内存空间。
so文件编译方法
–so文件的源文件中不需要有main函数,即使有也不会被执行。
–编译的时候gcc需要加-fPIC选项,这可以使gcc产生与位置无关的代码。
–连接的时候gcc使用-shared选项,指示生成一个共享库文件。
–共享库文件名要以lib开头,扩展名为.so。
编写so的例子。
int max(int a, int b)
{
if (a > b)
return a;
else
return b;
} int add(int a, int b)
{
return a + b;
}
#ifndef TEST_H_
#define TEST_H_ int max(int a, int b);
int add(int a, int b); #endif /* TEST_H_ */
.SUFFIXES:.c .o CC=gcc
SRCS=test.c EXEC=libtest.so OBJS=$(SRCS:.c=.o) start:$(OBJS)
$(CC) -shared -o $(EXEC) $(OBJS) .c.o:
$(CC) -g -fPIC -o $@ -c $< clean:
rm -f $(OBJS)
so文件使用方法
–为了让linux能找到so文件的位置,需要在.bash_profile中添加export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
–或者将so文件放入linux的系统目录/usr/lib/
–在c文件中使用so文件,首先需要 #inluce相关h文件。
–gcc连接时添加 –L参数指明so文件存放路径,-l参数指明so文件名
–以libtest.so文件在当前路径下举例
gcc -L. -ltest -o a a.o
其中-L.意思为在当前路径下寻找so文件
-ltest意思为要链接libtest.so这个库文件
-o a 意思为编译后的可执行文件名为a
u调用so的例子
#include "test.h"
#include <stdio.h> int main()
{
printf("%d\n", max(, ));
printf("%d\n", add(, ));
return ;
}
.SUFFIXES:.c .o
CC=gcc
SRCS=a.c
EXEC=a
OBJS=$(SRCS:.c=.o)
start:$(OBJS)
$(CC) -L. -ltest -o $(EXEC) $(OBJS)
.c.o:
$(CC) -o $@ -c $<
clean:
rm -f $(OBJS)
当我们在cpp文件中包含test.h文件,用g++链接libtest.so这个库时会报错:
(.text+0x19): undefined reference to `max(int, int)'
(.text+0x3d): undefined reference to `add(int, int)'
为了使我们编写的so文件同时可以被C或者C++调用,我们需要修改一下h文件中的函数申明部分。
增加带有__cplusplus的预编译指令。
__cplusplus是c++编译器预定义的一个宏,比如用g++的时候这个宏就被提前定义了
编写so的例子。
–test.h头文件
如果是c++编译器会默认定义__cplusplus这个宏。
当使用gcc编译的时候产生如下结果:
int max(int a, int b);
int add(int a, int b);
当使用g++编译的时候,产生如下结果:
extern "C"{
int max(int a, int b);
int add(int a, int b);
}
#ifndef TEST_H_
#define TEST_H_ #ifdef __cplusplus
extern "C"{
#endif int max(int a, int b);
int add(int a, int b); #ifdef __cplusplus
}
#endif #endif /* TEST_H_ */
最新文章
- Centos7 编译安装 Nginx PHP Mariadb Memcached 扩展 ZendOpcache扩展 (实测 笔记 Centos 7.3 + Mariadb 10.1.20 + Nginx 1.10.2 + PHP 7.1.0 + Laravel 5.3 )
- Linux_用户级_常用命令(5):rm
- IE9以下 placeholder兼容
- jface的CheckboxTreeViewer实现单选
- Linux进程间通信IPC学习笔记之管道
- win2008远程桌面卡顿和上传慢的解决方法
- 基于visual Studio2013解决C语言竞赛题之0705矩阵转置
- [原创]一种基于Python爬虫和Lucene检索的垂直搜索引擎的实现方法介绍
- 第九章——运行tensorflow(Up and Running with TensorFlow)
- string find()函数
- 【SerpentAI:Python开源游戏智能体开发框架——相比OpenAI Universe可导入自己的游戏、可脱离Docker/VNC运行】
- python Flask框架mysql数据库配置
- as3.0中如何阻止事件冒泡
- How to detect the types of executable files
- js中去除字符串两边的空格
- CUDA ---- Constant Memory
- C# 生成word文档(NPOI)
- js设置光标插入文字和HTML
- Mermaid 学习
- Eclipse下配置Maven
热门文章
- net Core 2.1新功能Generic Host(通用主机)
- JS计算字符串的长度
- jsp有哪些动作?作用分别是什么?
- linux swap交换分区说明/管理
- 解决 No module named PyQt5.QtWebKitWidgets
- [MySQL-MM] 生产环境自动恢复MM中一台M2库的过程,分享从零开始写的自动化重建脚本以及思路 (转)
- 用Json Template在Azure上创建Cisco CSR路由器
- 使用批处理自动发布IIS站点,基于IIS7及以上
- Day2-VIM(四):修改
- boost的asio接收单路大数据量udp包的方法