最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

將C++程序打包成SO庫并調(diào)用的詳細(xì)流程

 更新時間:2025年11月04日 10:03:21   作者:智驅(qū)千行  
在 Linux 系統(tǒng)中,SO(Shared Object)是動態(tài)鏈接庫,類似于 Windows 的 DLL,將 C++ 程序打包為 SO 庫可以實現(xiàn)代碼復(fù)用、隱藏實現(xiàn)細(xì)節(jié),并支持動態(tài)加載,以下是詳細(xì)的打包與調(diào)用流程,需要的朋友可以參考下

一、SO 庫的基本概念

  • 動態(tài)鏈接庫(SO):在程序運行時被加載,多個程序可共享同一 SO 庫,節(jié)省內(nèi)存
  • 優(yōu)點:減小可執(zhí)行文件體積、便于模塊更新(無需重新編譯主程序)
  • 核心:通過extern "C"解決 C++ 名稱修飾問題,確保庫函數(shù)能被正確識別

二、創(chuàng)建 SO 庫的步驟

1. 準(zhǔn)備源文件

假設(shè)有一個簡單的數(shù)學(xué)運算模塊,包含頭文件和實現(xiàn)文件:

math_utils.h(頭文件)

#ifndef MATH_UTILS_H
#define MATH_UTILS_H
 
// 用extern "C"包裹,避免C++名稱修飾
#ifdef __cplusplus
extern "C" {
#endif
 
// 加法
int add(int a, int b);
 
// 乘法
int multiply(int a, int b);
 
#ifdef __cplusplus
}
#endif
 
#endif // MATH_UTILS_H

math_utils.cpp(實現(xiàn)文件)

#include "math_utils.h"
 
// 加法實現(xiàn)
int add(int a, int b) {
    return a + b;
}
 
// 乘法實現(xiàn)
int multiply(int a, int b) {
    return a * b;
}

2. 編譯生成 SO 庫

使用g++編譯,關(guān)鍵參數(shù):

  • -fPIC:生成位置無關(guān)代碼(必選,確保庫可被多個程序共享)
  • -shared:指定生成動態(tài)鏈接庫
  • -o:指定輸出文件名(慣例以lib開頭,.so結(jié)尾)

編譯命令:

g++ -fPIC -shared -o libmath_utils.so math_utils.cpp

執(zhí)行后會生成libmath_utils.so文件

三、調(diào)用 SO 庫的兩種方式

方式 1:編譯時鏈接(靜態(tài)加載)

1. 編寫調(diào)用程序main.cpp

#include <iostream>
#include "math_utils.h"
 
int main() {
    int a = 10, b = 20;
    
    std::cout << "a + b = " << add(a, b) << std::endl;
    std::cout << "a * b = " << multiply(a, b) << std::endl;
    
    return 0;
}

2. 編譯調(diào)用程序

編譯時需要指定:

  • 庫所在路徑(-L.表示當(dāng)前目錄)
  • 庫名稱(-lmath_utils,省略lib前綴和.so后綴)

編譯命令:

g++ main.cpp -o main -L. -lmath_utils

3. 運行程序

直接運行生成的可執(zhí)行文件:

./main

可能的錯誤
若提示error while loading shared libraries: libmath_utils.so: cannot open shared object file: No such file or directory,解決方法:

  • 臨時方案:export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
  • 永久方案:將 SO 庫復(fù)制到/usr/lib/usr/local/lib目錄

方式 2:運行時動態(tài)加載(使用dlfcn.h)

這種方式無需在編譯時鏈接庫,可在程序運行中動態(tài)加載,適合插件化設(shè)計。

1. 編寫動態(tài)加載程序dynamic_main.cpp

#include <iostream>
#include <dlfcn.h>  // 動態(tài)加載頭文件
 
int main() {
    // 加載SO庫
    void* handle = dlopen("./libmath_utils.so", RTLD_LAZY);
    if (!handle) {
        std::cerr << "加載庫失敗: " << dlerror() << std::endl;
        return 1;
    }
 
    // 獲取函數(shù)指針(注意:函數(shù)指針類型必須與實際函數(shù)匹配)
    typedef int (*AddFunc)(int, int);
    AddFunc add = (AddFunc)dlsym(handle, "add");
    
    typedef int (*MultiplyFunc)(int, int);
    MultiplyFunc multiply = (MultiplyFunc)dlsym(handle, "multiply");
 
    // 檢查函數(shù)是否獲取成功
    const char* error;
    if ((error = dlerror()) != NULL) {
        std::cerr << "獲取函數(shù)失敗: " << error << std::endl;
        dlclose(handle);
        return 1;
    }
 
    // 調(diào)用函數(shù)
    int a = 10, b = 20;
    std::cout << "a + b = " << add(a, b) << std::endl;
    std::cout << "a * b = " << multiply(a, b) << std::endl;
 
    // 關(guān)閉庫
    dlclose(handle);
    return 0;
}

2. 編譯動態(tài)加載程序

需要鏈接動態(tài)加載庫-ldl

g++ dynamic_main.cpp -o dynamic_main -ldl

3. 運行程序

./dynamic_main

四、高級用法:帶類的 SO 庫

C++ 的類也可以封裝到 SO 庫中,但需要特殊處理(因為extern "C"不支持類)。

1. 定義帶純虛函數(shù)的接口類

calculator.h

#ifndef CALCULATOR_H
#define CALCULATOR_H
 
class Calculator {
public:
    // 純虛函數(shù)(接口)
    virtual int add(int a, int b) = 0;
    virtual int multiply(int a, int b) = 0;
    virtual ~Calculator() {} // 虛析構(gòu)函數(shù)
};
 
// 提供C風(fēng)格的創(chuàng)建和銷毀函數(shù)
extern "C" {
    Calculator* create_calculator();
    void destroy_calculator(Calculator* calc);
}
 
#endif // CALCULATOR_H

2. 實現(xiàn)接口類

calculator_impl.cpp

#include "calculator.h"
 
class CalculatorImpl : public Calculator {
public:
    int add(int a, int b) override {
        return a + b;
    }
    
    int multiply(int a, int b) override {
        return a * b;
    }
};
 
// 實現(xiàn)C風(fēng)格的創(chuàng)建和銷毀函數(shù)
extern "C" {
    Calculator* create_calculator() {
        return new CalculatorImpl();
    }
    
    void destroy_calculator(Calculator* calc) {
        delete calc;
    }
}

3. 編譯 SO 庫

g++ -fPIC -shared -o libcalculator.so calculator_impl.cpp

4. 調(diào)用帶類的 SO 庫

use_calculator.cpp

#include <iostream>
#include "calculator.h"
 
int main() {
    // 創(chuàng)建對象
    Calculator* calc = create_calculator();
    
    // 調(diào)用方法
    int a = 10, b = 20;
    std::cout << "a + b = " << calc->add(a, b) << std::endl;
    std::cout << "a * b = " << calc->multiply(a, b) << std::endl;
    
    // 銷毀對象
    destroy_calculator(calc);
    return 0;
}

編譯調(diào)用程序

g++ use_calculator.cpp -o use_calc -L. -lcalculator

五、注意事項

  1. 名稱修飾問題:C++ 會對函數(shù)名進行修飾(添加參數(shù)類型信息),必須用extern "C"包裹導(dǎo)出函數(shù),確保 C 風(fēng)格的函數(shù)名
  2. 版本兼容性:修改 SO 庫后,若函數(shù)簽名不變,調(diào)用程序無需重新編譯
  3. 內(nèi)存管理:在 SO 庫中分配的內(nèi)存,應(yīng)在同一庫中釋放,避免跨庫內(nèi)存管理問題
  4. 依賴問題:若 SO 庫依賴其他庫,需要確保這些庫在運行時可被找到
  5. 調(diào)試:可使用nm -D libxxx.so查看 SO 庫導(dǎo)出的函數(shù)列表

通過以上步驟,你可以將 C++ 代碼封裝為 SO 庫,并靈活地在其他程序中調(diào)用,這在大型項目模塊化開發(fā)中非常實用。

以上就是將C++程序打包成SO庫并調(diào)用的詳細(xì)流程的詳細(xì)內(nèi)容,更多關(guān)于C++程序打包成SO庫并調(diào)用的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論

长宁县| 漯河市| 怀宁县| 海南省| 和平县| 辉县市| 任丘市| 浙江省| 蓝田县| 泰州市| 山东省| 新宾| 大丰市| 瑞丽市| 石狮市| 临桂县| 宣汉县| 井研县| 盐源县| 长岛县| 临海市| 英超| 乌拉特中旗| 曲松县| 砀山县| 海安县| 石柱| 三都| 乐东| 凭祥市| 崇明县| 叶城县| 宜黄县| 塔城市| 连江县| 龙陵县| 饶阳县| 乐陵市| 微博| 铁力市| 昭平县|