一般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文件