一般c++的热更有两种方式

1、c++ 动态加载so的方式,也就是通过dlopen 、dlsym 、 dlclose 这三个函数操作实现热更

2、c++ 通过执行lua文件的形式,sol2(https://github.com/ThePhD/sol2)这是一个c++ 与 lua交互的开源库,已经支持lua5.3,c++14 c++17都已经支持了。

使用lua热更其实跟下面的代码方式差不多,在心跳出调用lua脚本,lua脚本可以 require “libact” ,获取c++ 方法,或者剩余的逻辑全部都由lua实现都是可以的。

这个lua脚本主要是分发功能使用。  

这里给出一个简单的c++ 通过动态库实现热更的例子

main.cpp

#include "Player.h"
#include <unistd.h>
#include <dlfcn.h>

typedef void (*FunPtr)(Player* player);

int main(int argc, char const *argv[])
{
    std::string soname = "./libact.so";
    Player player;
    while(1)
    {
        player.heartbeat();
        auto actHandler = dlopen(soname.c_str(), RTLD_LAZY);
        if(actHandler != nullptr)
        {
            FunPtr func;
            func = (FunPtr)dlsym(actHandler, "joinact");
            if(func)
            {
                (*func)(&player);
            }
            player.Print();
            dlclose(actHandler);
        }
        sleep(1);
    }
    return 0;
}

//g++ -g -o main main.cpp Player.h Player.cpp -ldl

Player.h

#pragma once

#include <map>
#include <string>
#include <ctime>
#include <iostream>

class ActInfo{
public:
    time_t begin;
    time_t end;
    int status{0}; //0 未参与 1参与中 2结束
};
class Player{
public:
    Player(){}
    virtual ~Player(){}
    void AddAct(const std::string& act)
    {
        auto it = m_act.find(act);
        if(it == m_act.end())
        {
            ActInfo info;
            info.begin = time(0);
            info.status = 1;
            m_act.emplace(act, info);
        }
    }

    void heartbeat()
    {
    }

    void Print()
    {
        auto it = m_act.begin();
        for (; it != m_act.end(); it++)
        {
            std::cout << it->first << std::endl;
        }
    }
private:
    std::map<std::string, ActInfo> m_act;
};

Player.cpp

#include "Player.h"

Activity.h

#pragma once

#include "Player.h"

class Activity{
public:
    //判断玩家可参与的活动
    void joinact(Player* player)
    {
        player->AddAct("xxxx");
        player->AddAct("xxxx2222");
    }
};

extern "C" void joinact(Player *player);

Activity.cpp


#include "Activity.h"
#include <iostream>
using namespace std;

void joinact(Player* player)
{
    Activity activity;
    activity.joinact(player);
    return;
}

编译so

CMakeLists.txt

cmake_minimum_required(VERSION 2.8)

project(act)

add_definitions(-D__LINUX__)

include_directories(./)

set(CMAKE_VERBOSE_MAKEFILE on)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -o2")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
set(CMAKE_C_COMPILER "gcc")
set(CMAKE_CXX_COMPILER "g++")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")


set(SOURCE_FILE Activity.cpp Player.cpp)
add_library(act SHARED  ${SOURCE_FILE})

target_link_libraries(act dl)

c++ 通过so热更需要注意几点

1、dlsym 加载的函数需要使用  extern "C" 声明,否则是找不到的

2、加载的动态库使用完后需要dlclose卸载,否则dlopen是无法加载最新的so文件

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐