菜鸟笔记
提升您的技术认知

c 反射实现—根据类名动态创建对象-ag真人官方网

我们在编写c 框架时,经常会涉及到一项基础技术,就是根据“一个动态库 一个类名称字符串“,动态的创建类对象。

这样做的好处是可以实现框架与业务代码的彻底解耦。框架不用关心业务侧的具体实现细节,只需要提供一个基类由业务方继承实现,然后业务方在配置文件中配置对应的动态库 类名称即可实现自动加载并运行。我们通常把这类功能称为classloader,今天就带大家一起来实现下。

一、实现原理

classloader一般包含shared_library动态库加载/卸载、object_factory动态对象创建工厂、class_register动态类注册,以及class_loader统一管理部分。整体关系如下图:

动态对象创建的关键是,框架不知道业务类的任何信息,所以需要业务侧在实现derived类(即图中democomponent)之后,使用register_class宏注册类以让框架知晓(注册时,宏需要自动为类生成一个creater方法并注册给objectfactory,因此保存注册信息的objectfactory需要使用单例)。

框架持有每个业务组件类的creater方法之后,在需要创建createobject时使用单例保存的业务类注册creater即可创建对应对象。

二、具体实现

1、shared_library动态库加载/卸载
这部分是最简单的,我们使用dlopen、dlclose来实现即可,简单的封装下,这里不赘述,我们重点讲解后续部分。

class sharedlibrary {
    ...
    bool load(const std::string &libraryfile){
        ...
        // load so 
        _libraryhandle = dlopen(libraryfile.c_str(), real_flag); 
        if (!_libraryhandle) { 
            const char *err = dlerror(); 
            log(error) << "library [" << libraryfile << "] load fail: " << std::string(err); 
            return false; 
        }
        ...
    }
    ...
    bool unload(){ 
        ...
        // unload so 
        if (_libraryhandle) { 
            log(info) << "unload"; 
            dlclose(_libraryhandle); 
            _libraryhandle = nullptr;
        }
        ...
    }
    ...
}

2、object_factory对象创建工厂与class_register动态类注册
object_factory对象工厂是classloader的核心,决定了如何完全松耦合的实现动态类创建。class_register作为辅助,为object_factory的预先注册提供宏支持。

2.1 新手入门
提到动态创建对象,相信新手想到的最简单的方法通常如下:

void createobject(std::string objname)
{
    if(objname == “a”)
    {
        new a;
    }
    else if(objname == “b”)
    {
        new b;
    }
    ...
}

但是这里有个问题,框架编写时并不知道业务要起什么类名,框架编译时也没有这些类的so库,又如何在代码中提前编写new 类名的代码呢?况且业务代码一直在变,框架怎么可能跟着业务变化一直修改这些地方呢?显然这种方法是不可行的。

2.2 宏注册
为了解决这个问题,接下来很多同学会想到可以用宏来实现传入字符串,new出对应的类,这个思路很好,所以我们接下来实现了一个宏定义:

// 动态注册类creator
#define register_class(classname)                                                            \
  classname *create##classname()                                                             \
  {                                                                                          \
    return new classname;                                                                    \
  }                                                                                          \
  static bool g_reg_##classname = objectfactory::getinstance()->register(#derived, create##uniqueid);

上面这个宏很简单,首先是定义了一个new对象的函数,new一个传入类名的对象。接着定义了一个static g_reg_xx变量,这个变量被初始化的时候,会调用到objectfactory::register来保存类名和类creater方法的关系。这里我们使用static getinstance单例函数,确保在所有static g_reg_xx对象构造之前,objectfactory单例对象已经完成了初始化。这里的static g_reg_xx变量也可以使用struct构造函数来代替,目的都是为了在加载register_class代码之后就能自动创建一个static对象,从而自动完成类注册动作。

接下来,我们要实现下register逻辑,这里比较简单,实现一个objectfactory单例,把register传入的类名和类creater方法保存下来备用即可:

class objectfactory{
        // 动态注册类
        using objcreator = std::function
网站地图