当前位置: 首页 > news >正文

C/C++ 模板与so

在Linux系统中,将相同的模板代码编译到两个不同的共享库(.so 文件)中是一种相对复杂的操作,通常并不推荐,因为这样做可能会导致符号冲突和二进制膨胀。然而,如果你确实有这样的需求,可以通过一些技巧来实现。

假设你有一个C++模板类 MyClass,并希望将其编译到两个不同的共享库中 libA.solibB.so。以下是实现这一目标的步骤:

  1. 创建模板类源代码

    创建一个头文件 MyClass.h,其中包含模板类的定义:

    // MyClass.h
    #ifndef MYCLASS_H
    #define MYCLASS_Htemplate <typename T>
    class MyClass {
    public:MyClass(T value) : value_(value) {}T getValue() const { return value_; }private:T value_;
    };#endif // MYCLASS_H
    
  2. 创建源文件(可选)

    通常情况下,模板类的实现是放在头文件中的,因为模板实例化需要在编译时完成。但如果你有模板类的实现需要放在源文件中,你可以这样做:

    // MyClass.cpp (可选)
    #include "MyClass.h"// 如果模板实现复杂,可以放在这里(但通常不推荐)
    

    注意:如果你选择将实现放在源文件中,你需要确保每个使用模板的编译单元(即每个 .cpp 文件)都能看到模板定义,这通常意味着你需要将头文件包含在每个使用模板的 .cpp 文件中。

  3. 创建两个共享库

    为了创建两个不同的共享库,你需要两个独立的构建脚本(如 MakefileCMakeLists.txt)。

    Makefile 示例

    # Makefile for libA.so
    CC = g++
    CFLAGS = -fPIC -shared
    TARGET_A = libA.soall:$(CC) $(CFLAGS) -o $(TARGET_A) MyClass.h  # 注意:这里通常不需要MyClass.cpp,除非有非模板代码clean:rm -f $(TARGET_A)# Makefile for libB.so
    # 可以复制上面的Makefile,然后重命名变量
    CC = g++
    CFLAGS = -fPIC -shared
    TARGET_B = libB.soall:$(CC) $(CFLAGS) -o $(TARGET_B) MyClass.hclean:rm -f $(TARGET_B)
    

    注意:在创建共享库时,通常不需要 .cpp 文件,因为模板类在头文件中实例化。

  4. 编译共享库

    使用 make 命令编译两个共享库:

    make -f Makefile_for_libA  # 假设你将第一个Makefile命名为Makefile_for_libA
    make -f Makefile_for_libB  # 假设你将第二个Makefile命名为Makefile_for_libB
    
  5. 使用共享库

    在你的应用程序中,你可以链接并使用这两个共享库。但是,你需要确保模板实例化在链接时不会发生冲突。这通常意味着你需要在每个共享库和最终的应用程序中正确地管理模板的实例化。

    // main.cpp
    #include <iostream>
    #include "MyClass.h"int main() {MyClass<int> objA(42);std::cout << "Value from libA: " << objA.getValue() << std::endl;// 注意:这里我们假设libB中的MyClass实例化和使用是隔离的// 实际情况中,你可能需要更复杂的机制来避免符号冲突// 比如使用命名空间或者不同的模板参数return 0;
    }
    

    编译和链接你的应用程序:

    g++ main.cpp -o myApp -L. -lA -lB -Wl,-rpath,.
    
  6. 处理潜在的符号冲突

    如果你发现链接时出现符号冲突,你可能需要使用一些高级技术,如:

    • 命名空间:将模板类放在不同的命名空间中。
    • 模板参数修改:为两个库中的模板类使用不同的模板参数。
    • 编译器特性:利用编译器特性(如GCC的 visibility 属性)来控制符号的导出。

请注意,将相同的模板代码编译到两个不同的共享库中通常是不推荐的,因为这增加了二进制大小和潜在的维护复杂性。如果可能的话,考虑将模板类放在一个共享的、单独的库中,并由其他库和应用程序链接这个共享库。


http://www.mrgr.cn/news/71878.html

相关文章:

  • 学习threejs,使用第一视角控制器FirstPersonControls控制相机
  • CSS:导航栏三角箭头
  • 3216. 交换后字典序最小的字符串
  • SwiftUI开发教程系列 - 第十二章:本地化与多语言支持
  • django入门【05】模型介绍——字段选项(二)
  • android dvr黑屏
  • 十六、多版本并发控制
  • 【大数据测试HBase数据库 — 详细教程(含实例与监控调优)】
  • 速盾:CDN和OBS能共用流量包吗?
  • 解决MySQL中整型字段条件判断禁用不生效的问题
  • excel常用技能
  • 电商系统表的1-n如何设计?情景分析
  • 基于Multisim温度计温度测量检测测量系统电路(含仿真和报告)
  • 【AI日记】24.11.12 东京贫困女子读后感 | 未来学习工作时间分配
  • Python模块练习2(dict)
  • arcgis for js实现popupTemplate弹窗field名称和值转义
  • MySQl基础----Linux下数据库的密码和数据库的存储引擎(内附 实操图和手绘图 简单易懂)
  • PCL 点云分割 基于超体素的分割
  • 线上问题的排查之MySQL死锁如何排查
  • 25浙江省考-专项刷题(资料分析)-错题本
  • 力扣 LeetCode 142. 环形链表II(Day2:链表)
  • 字节青训-多米诺骨牌均衡状态、红包运气排行榜
  • SQL练习(2)
  • Python 进阶函数教程
  • xxl-job报错Connection refused: connect(连接被拒绝)
  • PostgreSQL序列:创建、管理与高效应用指南