生成 .so 和使用 .so

是哟ing两个最简单的项目演示使用 c++ 项目生成 .so 和在 c++ 项目中使用 .so

项目1:生成 .so 文件 (maker_so)

项目结构

复制代码
maker_so/
├── include/
│   └── calculator.h
├── src/
│   └── calculator.cpp
└── CMakeLists.txt

文件内容

include/calculator.h

cpp 复制代码
#ifndef CALCULATOR_H
#define CALCULATOR_H

extern "C" {
    int add(int a, int b);
    int subtract(int a, int b);
    int multiply(int a, int b);
    float divide(int a, int b);
}

#endif

src/calculator.cpp

cpp 复制代码
#include "calculator.h"

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

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

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

float divide(int a, int b) {
    if (b == 0) return 0;
    return (float)a / b;
}

CMakeLists.txt

cmake 复制代码
cmake_minimum_required(VERSION 3.10)
project(maker_so)

# 设置库的输出目录为项目下的 lib
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)

# 包含头文件目录
include_directories(${CMAKE_SOURCE_DIR}/include)

# 创建动态库
add_library(calculator SHARED src/calculator.cpp)

message(STATUS "Building calculator shared library")

构建项目1

bash 复制代码
# 创建并进入项目目录
mkdir -p maker_so/{include,src,build}
cd maker_so

# 创建文件(使用上面的内容)
# ... 创建 calculator.h, calculator.cpp, CMakeLists.txt

# 构建
cd build
cmake ..
cmake --build .

# 查看生成的 .so
ls -l ../lib/
# 应该看到: libcalculator.so

项目2:使用 .so 文件 (user_so)

项目结构

复制代码
user_so/
├── lib/                    # 从项目1复制过来的 .so
│   └── libcalculator.so
├── include/                # 从项目1复制过来的头文件
│   └── calculator.h
├── src/
│   └── main.cpp
└── CMakeLists.txt

文件内容

include/calculator.h(从项目1复制)

cpp 复制代码
#ifndef CALCULATOR_H
#define CALCULATOR_H

extern "C" {
    int add(int a, int b);
    int subtract(int a, int b);
    int multiply(int a, int b);
    float divide(int a, int b);
}

#endif

src/main.cpp

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

int main() {
    int a = 15, b = 4;
    
    std::cout << "=== Using calculator library ===\n";
    std::cout << a << " + " << b << " = " << add(a, b) << std::endl;
    std::cout << a << " - " << b << " = " << subtract(a, b) << std::endl;
    std::cout << a << " * " << b << " = " << multiply(a, b) << std::endl;
    std::cout << a << " / " << b << " = " << divide(a, b) << std::endl;
    
    return 0;
}

CMakeLists.txt

cmake 复制代码
cmake_minimum_required(VERSION 3.10)
project(user_so)

# 设置可执行文件输出目录
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)

# 设置 RPATH,让程序能在 lib 目录找到 .so
set(CMAKE_INSTALL_RPATH "${CMAKE_SOURCE_DIR}/lib")
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)

# 包含头文件目录
include_directories(${CMAKE_SOURCE_DIR}/include)

# 指定库文件目录
link_directories(${CMAKE_SOURCE_DIR}/lib)

# 创建可执行文件
add_executable(calc_app src/main.cpp)

# 链接动态库
target_link_libraries(calc_app calculator)

message(STATUS "Building application that uses calculator.so")

完整的一键构建脚本

创建一个脚本 build_all.sh 来自动化整个过程:

bash 复制代码
#!/bin/bash

echo "=== 项目1: 生成 libcalculator.so ==="

# 创建项目1
mkdir -p maker_so/{include,src,build}

# 创建项目1的文件
cat > maker_so/include/calculator.h << 'EOF'
#ifndef CALCULATOR_H
#define CALCULATOR_H

extern "C" {
    int add(int a, int b);
    int subtract(int a, int b);
    int multiply(int a, int b);
    float divide(int a, int b);
}

#endif
EOF

cat > maker_so/src/calculator.cpp << 'EOF'
#include "calculator.h"

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

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

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

float divide(int a, int b) {
    if (b == 0) return 0;
    return (float)a / b;
}
EOF

cat > maker_so/CMakeLists.txt << 'EOF'
cmake_minimum_required(VERSION 3.10)
project(maker_so)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)
include_directories(${CMAKE_SOURCE_DIR}/include)
add_library(calculator SHARED src/calculator.cpp)
EOF

# 构建项目1
cd maker_so
mkdir -p build
cd build
cmake ..
cmake --build .
cd ../..

echo -e "\n=== 项目2: 使用 libcalculator.so ==="

# 创建项目2
mkdir -p user_so/{include,src,build,lib}

# 从项目1复制 .so 和头文件到项目2
cp maker_so/lib/libcalculator.so user_so/lib/
cp maker_so/include/calculator.h user_so/include/

# 创建项目2的文件
cat > user_so/src/main.cpp << 'EOF'
#include <iostream>
#include "calculator.h"

int main() {
    int a = 15, b = 4;
    
    std::cout << "=== Using calculator library ===\n";
    std::cout << a << " + " << b << " = " << add(a, b) << std::endl;
    std::cout << a << " - " << b << " = " << subtract(a, b) << std::endl;
    std::cout << a << " * " << b << " = " << multiply(a, b) << std::endl;
    std::cout << a << " / " << b << " = " << divide(a, b) << std::endl;
    
    return 0;
}
EOF

cat > user_so/CMakeLists.txt << 'EOF'
cmake_minimum_required(VERSION 3.10)
project(user_so)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
set(CMAKE_INSTALL_RPATH "${CMAKE_SOURCE_DIR}/lib")
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
include_directories(${CMAKE_SOURCE_DIR}/include)
link_directories(${CMAKE_SOURCE_DIR}/lib)
add_executable(calc_app src/main.cpp)
target_link_libraries(calc_app calculator)
EOF

# 构建项目2
cd user_so
mkdir -p build
cd build
cmake ..
cmake --build .
cd ../..

echo -e "\n=== 运行结果 ==="
./user_so/bin/calc_app

echo -e "\n=== 项目文件列表 ==="
echo "项目1生成的 .so:"
ls -l maker_so/lib/
echo -e "\n项目2使用的 .so:"
ls -l user_so/lib/
echo -e "\n项目2生成的可执行文件:"
ls -l user_so/bin/

手动构建步骤(如果没有脚本)

构建项目1

bash 复制代码
cd maker_so
mkdir build && cd build
cmake ..
make
cd ../..

复制文件到项目2

bash 复制代码
mkdir -p user_so/lib user_so/include
cp maker_so/lib/libcalculator.so user_so/lib/
cp maker_so/include/calculator.h user_so/include/

构建项目2

bash 复制代码
cd user_so
mkdir build && cd build
cmake ..
make
cd ../..

运行

bash 复制代码
./user_so/bin/calc_app

验证 .so 文件

bash 复制代码
# 查看 .so 的符号
nm -D user_so/lib/libcalculator.so

# 查看可执行文件的依赖
ldd user_so/bin/calc_app

# 运行程序
./user_so/bin/calc_app

这样就完成了:

  1. 项目1 生成了 libcalculator.so
  2. 项目2 使用了这个 .so 文件
  3. 所有文件都放在各自的项目目录下,互不干扰
相关推荐
土司大王6 小时前
LeetCode hot100——对称二叉树
算法·leetcode·职场和发展
sali-tec7 小时前
C# 基于OpenCv的视觉工作流-章106-差值追踪
图像处理·人工智能·opencv·算法·计算机视觉
单线程_017 小时前
从案例分析 Vue3 Tokenizer 源码一
前端·javascript·vue.js
Navigator_Z7 小时前
LeetCode //C - 1208. Get Equal Substrings Within Budget
c语言·算法·leetcode
手写码匠7 小时前
Dify 多 Agent 工具权限与安全沙箱实战:让智能体“有能力,但不越权“
人工智能·深度学习·算法·aigc
黎阳之光7 小时前
打破堆场感知黑盒:黎阳之光视频孪生,构建港口码头网格化透明管控新体系
大数据·人工智能·算法·安全·数字孪生
丘山一郎8 小时前
Spring 中的IOC控制反转 和DI依赖注入
java·后端·spring
码视野8 小时前
基于 Spring Boot + Vue3 的【大学英语四六级 (CET-4/6) 作文智能评分与句式润色系统】设计与实现(含PRD/三端高保真源码/大屏)
java·前端·人工智能·spring boot·后端·vue3
MetaLite8 小时前
Spring-AOP自调用为什么失效-AopContext真能解决吗
java·后端·spring
大模型码小白8 小时前
AI 对话流性能调优:万级消息的虚拟滚动落地
java·大数据·前端·javascript·人工智能·算法·机器学习