C++在Linux上生成动态库并调用接口测试

加减乘除demo代码

项目结构

CPP/

├── calculator.cpp

├── calculator.h

├── main.cpp

头文件

c 复制代码
#ifndef CALCULATOR_H
#define CALCULATOR_H

#ifdef __cplusplus
extern "C" {
    #endif

    double add(double a, double b);
    double subtract(double a, double b);
    double multiply(double a, double b);
    double divide(double a, double b);

    #ifdef __cplusplus
}
#endif

#endif // CALCULATOR_H

源文件

c 复制代码
#include "calculator.h"
#include <iostream>

double add(double a, double b) {
    return a + b;
}

double subtract(double a, double b) {
    return a - b;
}

double multiply(double a, double b) {
    return a * b;
}

double divide(double a, double b) {
    if (b == 0) {
        std::cerr << "错误:除数不能为0!" << std::endl;
        return 0;
    }
    return a / b;
}

main.cpp测试

main.cpp,用于测试动态库接口,需要在编译好动态库后进行测试

c 复制代码
#include <iostream>
#include "calculator.h"

int main() {
    double a = 8, b = 2;
    std::cout << "加法: " << add(a, b) << std::endl;
    std::cout << "减法: " << subtract(a, b) << std::endl;
    std::cout << "乘法: " << multiply(a, b) << std::endl;
    std::cout << "除法: " << divide(a, b) << std::endl;
    return 0;
}

编译动态库

  1. -fPIC:为共享库生成位置无关代码
  2. -shared:生成共享库
  3. -o libcalculator.so:输出为动态库文件
c 复制代码
g++ -fPIC -shared calculator.cpp -o libcalculator.so

查看动态库有哪些接口

nm命令

c 复制代码
nm -D libcalculator.so

带有 T 的(代表函数定义在库里)

信息比较多可以加grep命令进行过滤

objdump命令

c 复制代码
objdump -T libcalculator.so

readelf命令

c 复制代码
readelf -Ws libcalculator.so

main.cpp编译

main.cpp会在编译的过程中去动态链接libcalculator.so

  1. -L.:告诉编译器去当前目录查找库文件
  2. -lcalculator:链接名为 libcalculator.so 的库(省略前缀 lib 和扩展名 .so
c 复制代码
g++ main.cpp -L. -lcalculator -o main

执行测试程序

运行程序前,设置动态库路径

  1. LD_LIBRARY_PATH 是 Linux 下指定"运行时动态库查找路径"的环境变量
  2. . 代表当前目录
  3. $LD_LIBRARY_PATH 是保留已有路径
c 复制代码
#设置环境变量
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH

上面代码的意思是:请系统在当前目录找动态库,然后再去默认路径找

系统默认会查找这些路径

  1. /lib
  2. /usr/lib

永久添加路径

更新系统的动态链接库缓存 ,也就是告诉系统有哪些 .so 库、它们在哪儿,以便程序运行时可以找到这些库。

c 复制代码
sudo ldconfig
什么时候用?
  1. 安装了新的 .so 动态库
  2. .so 文件放到了非标准路径下(比如 /usr/local/lib/opt/mylibs
  3. 修改了 /etc/ld.so.conf/etc/ld.so.conf.d/ 下的配置

运行程序

c 复制代码
./main

运行程序前,为什么要设置动态库路径

因为你用的是 动态链接库( **.so**** 文件),程序运行时需要知道这个库 在哪里**。编译的时候你告诉了编译器怎么找到它(-L.),但运行时要靠系统的**动态链接器(ld.so)**来加载 .so 文件。

如果 .so 不在系统默认的路径里(比如 /lib, /usr/lib),就需要你手动告诉它去哪里找。

python调用

test_calculator.py

c 复制代码
import ctypes
import os

# 加载动态库
lib_path = os.path.abspath("libcalculator.so")
calculator = ctypes.CDLL(lib_path)

# 设置参数和返回类型
calculator.add.argtypes = [ctypes.c_double, ctypes.c_double]
calculator.add.restype = ctypes.c_double

calculator.subtract.argtypes = [ctypes.c_double, ctypes.c_double]
calculator.subtract.restype = ctypes.c_double

calculator.multiply.argtypes = [ctypes.c_double, ctypes.c_double]
calculator.multiply.restype = ctypes.c_double

calculator.divide.argtypes = [ctypes.c_double, ctypes.c_double]
calculator.divide.restype = ctypes.c_double

# 测试调用
a = 10.0
b = 2.0

print("加法:", calculator.add(a, b))
print("减法:", calculator.subtract(a, b))
print("乘法:", calculator.multiply(a, b))
print("除法:", calculator.divide(a, b))

测试调用

  1. export LD_LIBRARY_PATH=CPP:$LD_LIBRARY_PATH
  2. python3 test_calculator.py

Makefile生成动态库

c 复制代码
# Makefile for building libcalculator.so shared library

# 编译器
CXX = g++

# 编译选项
CXXFLAGS = -fPIC -Wall -Wextra -O2

# 目标名称
TARGET = libcalculator.so

# 源码文件
SRC = calculator.cpp

# 头文件
HEADER = calculator.h

# 输出路径(当前目录)
OBJ = $(SRC:.cpp=.o)

# 默认目标
all: $(TARGET)

# 生成共享库
$(TARGET): $(OBJ)
	$(CXX) -shared -o $@ $^

# 编译cpp为.o文件
%.o: %.cpp $(HEADER)
	$(CXX) $(CXXFLAGS) -c $< -o $@

# 清理生成的文件
clean:
	rm -f $(OBJ) $(TARGET)

.PHONY: all clean

运行make

Makefile一起生成动态库和可执行程序

c 复制代码
# 编译器
CXX = g++

# 编译选项
CXXFLAGS = -fPIC -Wall -Wextra -O2

# 生成共享库的目标
LIB_NAME = libcalculator.so

# 可执行文件名
EXEC = main

# 源文件
LIB_SRC = calculator.cpp
MAIN_SRC = main.cpp

# 对应的中间目标
LIB_OBJ = $(LIB_SRC:.cpp=.o)
MAIN_OBJ = $(MAIN_SRC:.cpp=.o)

# 默认目标
all: $(LIB_NAME) $(EXEC)

# 生成共享库
$(LIB_NAME): $(LIB_OBJ)
	$(CXX) -shared -o $@ $^

# 编译 main,链接动态库
$(EXEC): $(MAIN_OBJ) $(LIB_NAME)
	$(CXX) -o $@ $(MAIN_OBJ) -L. -lcalculator

# 通用规则:.cpp -> .o
%.o: %.cpp
	$(CXX) $(CXXFLAGS) -c $< -o $@

# 运行程序
run: all
	LD_LIBRARY_PATH=. ./$(EXEC)

# 清理
clean:
	rm -f *.o $(LIB_NAME) $(EXEC)

.PHONY: all run clean

运行make

用CMakeLists管理

项目结构

CPP/

├── calculator.cpp

├── calculator.h

├── main.cpp

└── CMakeLists.txt

CMakeLists.txt

c 复制代码
cmake_minimum_required(VERSION 3.10)
project(CalculatorProject)

# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)

# 输出到 build 目录下的 bin 和 lib 子目录
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)

# 添加库(生成 libcalculator.so)
add_library(calculator SHARED calculator.cpp)

# 添加可执行文件
add_executable(main main.cpp)

# 链接共享库
target_link_libraries(main PRIVATE calculator)

# 设置头文件搜索路径
target_include_directories(main PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(calculator PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})

使用方法

  1. mkdir build && cd build
  2. cmake ...
  3. cmake --build .

目录结构

CPP/

├── calculator.cpp

├── calculator.h

├── main.cpp

├── CMakeLists.txt

└── build/

复制代码
├── bin/

│   └── main

└── lib/

    └── libcalculator.so
相关推荐
王闯写bug43 分钟前
linux一次启动多个jar包
linux·jar
脑子慢且灵1 小时前
计算机操作系统——存储器管理
linux·服务器·windows·操作系统·存储器·存储器多级结构
1024熙1 小时前
【C++】——lambda表达式
开发语言·数据结构·c++·算法·lambda表达式
小码过河.1 小时前
CentOS 安装 Docker
linux·docker·centos
HappyGame022 小时前
Linux命令-vim编辑
linux·vim
笑远2 小时前
Vim/Vi 常用命令速查手册
linux·编辑器·vim
撒旦骑路西法,大战吕布2 小时前
如果你在使用 Ubuntu/Debian:使用 apt 安装 OpenSSH
linux·ubuntu·debian
mahuifa2 小时前
(2)VTK C++开发示例 --- 绘制多面锥体
c++·vtk·cmake·3d开发
_李筱夜2 小时前
ubuntu桌面版使用root账号进行登录
linux·ubuntu
23级二本计科3 小时前
C++ Json-Rpc框架-3项目实现(2)
服务器·开发语言·c++·rpc