加载lua脚本的热更新探测
Posted qianbo_insist
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了加载lua脚本的热更新探测相关的知识,希望对你有一定的参考价值。
上一篇文章
c++与lua socket 高级调用
下面要进行热更新的文件调用,要做到更改lua文件时,重新启动脚本。这样不用重启c++服务。根据探测几种方式,最终认为使用libuv的文件监控比较简单,跨平台,QT也可以使用QT自身带的文件监控功能。
linux 文件监控
inotify,比较好用,和windowsapi类似
int inotify_init(void);
int inotify_add_watch(int fd, const char *pathname, uint32_t mask);
int inotify_rm_watch(int fd, uint32_t wd);
windows文件监控
可以使用windows 的api 来监控文件夹,ReadDirectoryChangesW ,主要代码如下所示
HANDLE hDir;
char notify1024;
DWORD cbBytes,i;
char AnsiChar3;
wchar_t UnicodeChar2;
CString path;
FILE_NOTIFY_INFORMATION *pnotify=(FILE_NOTIFY_INFORMATION *)notify;
FILE_NOTIFY_INFORMATION *tmp;
GetCurrentDirectory(MAX_PATH,path.GetBuffer(MAX_PATH+1));
hDir = CreateFile( path, FILE_LIST_DIRECTORY,
FILE_SHARE_READ |
FILE_SHARE_WRITE |
FILE_SHARE_DELETE, NULL,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS |
FILE_FLAG_OVERLAPPED, NULL);
if (hDir == INVALID_HANDLE_VALUE)
dlg->m_edit.ReplaceSel("hDir:INVALID_HANDLE_VALUE\\r\\n");
return 0;
while (TRUE)
if(ReadDirectoryChangesW(hDir, ¬ify, sizeof(notify),
FALSE, FILE_NOTIFY_CHANGE_FILE_NAME| FILE_NOTIFY_CHANGE_LAST_WRITE,
&cbBytes, NULL, NULL))
tmp = pnotify;
switch(tmp->Action)
case FILE_ACTION_ADDED:
dlg->m_edit.ReplaceSel("Directory/File added (添加文件)- \\r\\n");
break;
case FILE_ACTION_REMOVED:
dlg->m_edit.ReplaceSel("Directory/File removed (删除文件)- \\r\\n");
break;
case FILE_ACTION_MODIFIED:
dlg->m_edit.ReplaceSel("Directory/File modified (修改文件内容)- \\r\\n");
break;
case FILE_ACTION_RENAMED_OLD_NAME:
dlg->m_edit.ReplaceSel("Directory/File old name (修改文件名字)- \\r\\n");
break;
case FILE_ACTION_RENAMED_NEW_NAME:
dlg->m_edit.ReplaceSel("Directory/File new name - \\r\\n");
break;
default:
break;
QT
QT可以使用QFileSystemWatcher* watcher 来监视文件,还是比较好用的
使用libuv
使用libuv的好处是跨平台,异步,非常好用,比QT的监控更加简单
#include <iostream>
#include <assert.h>
#include <stdio.h>
#include <fcntl.h>
#ifndef _WIN32
#include <unistd.h>
#endif
#include <uv.h>
#ifdef _WIN32
#include <WinSock2.h>
#include <windows.h>
#pragma comment(lib,"ws2_32.lib")
#pragma comment(lib,"psapi.lib")
#pragma comment(lib,"Iphlpapi.lib")
#pragma comment(lib,"Userenv.lib")
#endif
uv_loop_t* loop;
const char* command;
void run_command(uv_fs_event_t* handle, const char* filename, int events, int status)
char path[1024];
size_t size = 1023;
// Does not handle error if path is longer than 1023.
uv_fs_event_getpath(handle, path, &size);
path[size] = '\\0';
fprintf(stderr, "Change detected in %s: ", path);
if (events & UV_RENAME)
fprintf(stderr, "renamed");
if (events & UV_CHANGE)
fprintf(stderr, "changed");
fprintf(stderr, " %s\\n", filename ? filename : "");
// system(command);
int main(int argc, char** argv)
loop = uv_default_loop();
command = "dir";// argv[1];
const char* file = "udp.lua";
fprintf(stderr, "Adding watch on %s\\n", file);
uv_fs_event_t* fs_event_req = (uv_fs_event_t * )malloc(sizeof(uv_fs_event_t));
uv_fs_event_init(loop, fs_event_req);
// The recursive flag watches subdirectories too.
uv_fs_event_start(fs_event_req, run_command,file , UV_FS_EVENT_RECURSIVE);
return uv_run(loop, UV_RUN_DEFAULT);
以下为lua脚本
local socket = require("socket.core")
local udp = socket.udp()
local host = host or '127.0.0.1'
local port = '6000'
udp:settimeout(10)
--local udpbind = udp:bind(host,port)
udp:setsockname(host, port)
print('waiting client connect')
while 1 do
local revbuff,receip,receport = udp:receivefrom()
if (revbuff and receip and receport) then
recv(revbuff)
else
print('waiting client connect-1')
end
end
udp:close()
当我们修改lua脚本时
可以监控到文件改变,这时候可以停止lua运行,然后重启线程,做到热更新,这个下一次再实验。
以上是关于加载lua脚本的热更新探测的主要内容,如果未能解决你的问题,请参考以下文章
菜鸟学习 - Unity中的热更新 - LuaInterface用户指南
Unity3D热更新之LuaFramework篇[05]--Lua脚本调用c#以及如何在Lua中使用Dotween