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

Linux下C++编程使用动态链接库

在《Linux下C编程使用动态链接库》一文中已了解到了C语言里如何使用共享库SO了,但在C++里可全是类,该如何实现呢?C语言中的操作只能导出全局函数,并不能导出类的方法,故而需要设计相关的全局函数来封装一层。这里用到了“类工厂函数”的设计模式,定义一个抽象类(含有纯虚函数)的头文件,然后在SO源文件和使用的源文件里均包含该头文件,在SO里继承并实现抽象类里的纯虚函数。具体看下面的实例,头文件里创建多边形类(作为接口),而在SO继承它并实现三角形类,并且设计了全局的创建和销毁类对象的函数:

polygon.hpp(纯虚父类,多边形类):

#ifndef POLYGON_HPP
#define POLYGON_HPP

class polygon {
protected:
        double _side_length;

public:
        polygon() : _side_length(0) {}
        virtual ~polygon() {}

        void set_side_length(double side_length) {
                _side_length = side_length;
        }

        virtual double area() const = 0;
};

typedef polygon* create_t();
typedef void destroy_t(polygon*);

#endif

triangle.cpp(三角形类,继承多边形类,实现其纯虚函数):

#include "polygon.hpp"
#include <math.h>

class triangle : public polygon {
public:
        virtual double area() const {
                return _side_length * _side_length * sqrt(3) / 2;
        }
};

extern "C" polygon* create() {
        return new triangle;
}

extern "C" void destroy(polygon* p) {
        delete p;
}

cppso_exam.cpp:

#include "polygon.hpp"
#include <iostream>
#include <dlfcn.h>

using namespace std;

int main()
{
        void * triangle_handle = dlopen("./triangle.so", RTLD_LAZY);
        if (!triangle_handle) {
                cerr << "dlopen failed: " << dlerror() << '\n';
                return -1;
        }

        create_t * create_triangle = (create_t *)dlsym(triangle_handle, "create");
        const char * dlsym_error = dlerror();
        if (dlsym_error) {
                cerr << "Cannot load symbol 'create' : " << dlsym_error << '\n';
                return -1;
        }

        destroy_t * destroy_triangle = (destroy_t *)dlsym(triangle_handle, "destroy");
        dlsym_error = dlerror();
        if (dlsym_error) {
                cerr << "Cannot load symbol 'destroy' : " << dlsym_error << '\n';
                return -1;
        }

        polygon * poly = create_triangle();
        poly->set_side_length(8);
        cout << "The area is : " << poly->area() << '\n';
        destroy_triangle(poly);

        dlclose(triangle_handle);

        return 0;
}

Makefile:

all:
        g++ -o triangle.so -shared -fPIC triangle.cpp
        g++ -rdynamic -o cppso cppso_exam.cpp -ldl

clean:
        rm -rf triangle.so cppso

相应的源码文件目录树如下: 

/home/xinu/xinu/c_cpp/cpp_so_example/ 
├── cppso_exam.cpp 
├── Makefile
├── polygon.hpp 
└── triangle.cpp 

我们在实现SO的triangle.cpp文件里看到了extern “C”,主要是为了处理Name Mangling的问题,即在C语言里函数名对应的符号名仍是函数名,而在C++里要支持函数重载,函数名对应的符号名则是函数名再加上参数名等组成,加上extern “C”是避免C++代码里找不到C函数(名字被改了),后期再详细说明该问题。

至此,我们了解了在类中进行共享库的处理方法。 


http://www.kler.cn/news/284905.html

相关文章:

  • Openldap可视化工具PhpLdapAdmin服务配置
  • TMPDIR在pip|pip3 install时的作用以及tmp只有noexec权限的解决方法
  • 问题记录之Qt Creator下qDebug中文乱码
  • SparkSQL缓存的用法
  • IM社交-前言
  • 负载均衡的分类有哪些?
  • 路由策略工具
  • 51单片机——模块化编程
  • Kafka分布式集群部署实战:跨越理论,直击生产环境部署难题与解决方案,性能调优、监控与管理策略大揭秘,轻松上手分布式消息中间件
  • 【SQL基础】【leetcode】SQL50题
  • 『功能项目』技能释放【08】
  • Java设计模式【解释器模式】-行为型
  • 【QT线程学习】
  • PowerDesigner16.5 从mysql5.7逆向工程
  • ClickHouse的安装教程
  • 计算机网络概述(Internet结构和ISP)
  • matlab仿真 信道编码和交织(下)
  • 【docker】docker学习笔记
  • Datawhale AI夏令营 第五期 CV方向 Task3笔记
  • GD - GD32350R_EVAL - PWM实验和验证1
  • React原理之Diff算法
  • ESP32-S3 IDF框架 控制 WS2812 灯条:实现多种灯效
  • 【通过h5作为中转页跳转到微信小程序】
  • 【Linux】06.Linux 下的编译器——gcc/g++
  • 【C++ 第十八章】C++11 新增语法(2)
  • vue3+el-tale封装(编辑、删除、查看详情按钮一起封装)
  • 【HarmonyOS 4.0】@ohos.router 页面路由
  • ★ 算法OJ题 ★ 力扣11 - 盛水最多的容器
  • sqlite3 数据插入效率
  • YOLOv8改进 | 模块缝合 | C2f融合卷积重参数化OREPA【CVPR2022】