Hazel 2024

  1. 不喜欢游戏的人也可以做引擎,比如 cherno

  2. 引擎的作用主要是有两点:

    1. 将数据可视化
    2. 交互
  3. 当然有些引擎的功能也包含有制作数据文件,称之为资产 assets

  4. 不做窗口类的应用栈,可能要花一年才能做一个能实际使用的应用,只需要在游戏引擎中创建一个像 ImGUI 之类的关卡编辑器

    类似于着色编译器

目录

  • 设计
  • 开发
    • 属性配置
    • EntryPoint 入口
    • Logging Library 日志记录
    • premake 构建系统
    • 事件系统
    • 事件系统(下)_实现
      • KeyEvent: 重点
    • 预编译头
  • 技巧
    • Git
    • VS
    • 其他
  • 报错
    • 找不到头文件
    • Sandbox.exe 无法找到入口
    • inconsistent dll linkage 不一致的 dll 链接
    • error LNK2019: 无法解析的外部符号 & fatal error LNK1120: 1 个无法解析的外部命令
    • error LNK2019: 无法解析的外部符号,函数 main 中引用了该符号
    • git push origin main报错 连接不到 443
    • git 拉取超时
    • error C2597: 对非静态成员的非法引用
    • error C2039: "stdout_color_mt": 不是 "spdlog" 的成员
    • error C2040: 间接寻址级别不同
    • 弹窗报错:Sandbox.exe 无法找到入口
    • No Premake script (premake5.lua) found!
    • Error: [string "src/base/api.lua"]:606: bad argument #2 to 'deferredjoin' (string expected, got table)
    • error MSB3191: 无法创建目录,因为同名文件或目录已存在。
    • error MSB3073

设计

  1. EntryPorint:控制了什么,

  2. Apllication Layer
    整个窗口
    处理应用的生命周期和事件,比如运行循环,什么能保持应用运行并渲染帧,什么能够推动时间发展,什么能够执行游戏想要执行的所有代码,什么是事件,窗口调整大小或者关闭,输入事件,鼠标和键盘。需要一种方法来运行游戏或引擎,作为一个实际的应用运行在任意平台

  3. Window Layer
    渲染的目标地,输入事件将来自哪里,整个应用就是这个窗口,和平台支持和渲染接口支持有关

    • 输入
    • 事件:事件管理器
      • 处理输入
      • 广播功能:订阅事件并获得通知
  4. Render

    引擎最重要占比最大的一部分,很多引擎教程都是从渲染器开始。但是自己做一个引擎会从调试器开始,其实当其他部分都完成的时候,渲染器的构建将会变得非常简单

    通常是每帧一次

  5. Render API (OpenGL 是最简单的接口,跨平台)

    最后 Hazel 将会支持多种渲染接口,如 Vulcan(在实现一些东西的时候会比 OpenGL 更高效)

  6. Debugger Support

  7. Scripting Language

    不用一直写 c++

  8. Memory Systems

    内存对于性能而言很重要,比如分配内存的时候CPU的耗时

    自定义分配器和内存跟踪

  9. Entity-Compoennt-System(ECS)
    实体-组件系统,模块化游戏制作过程,能够包含特定的组件

  10. Physics

  11. File I/O, VFS(virtual file system)

  12. Build System

    能够把现有的 3D 模型或者资产自动导入引擎变成优化后的资产格式

    能够在 photoshop 更改后事实热更新到引擎内

开发

  1. 视频是 VS2017,视频中讲到过,但是 github 文档说 VS2019 也可以

  2. git clone https://github.com/xieyouchen/Hazel Git 这一句指令是把 Hazel 项目拷贝到 Git 空文件夹(如果没有创建 Git 空文件夹会自动创建),把里面的所有文件(包括隐藏文件)拷贝到本地的 Hazel 文件夹。

    如果只是 git clone … 那么会在指定位置先创建一个 Hazel 文件夹,再 clone 下 github 内所有资源
    为什么不先 clone 到空文件夹,然后再创建 VS 解决方案?其实是一样的,都需要手动迁移一下文件内容,因为 git clone 克隆下来的文件夹和 vs 创建解决方案时创建的文件夹应该处于同一文件层级

  3. 使用动态链接,将引擎和制作的可执行文件 .exe 动态链接,可以自定义加载或者卸载某些部分,会存在很多依赖项链接到引擎的 engine.dll,再将 engine.dll 链接到游戏

    c++系列有个视频介绍过动态链接和静态链接的区别,以及动态库和静态库,总的来说就是静态库会臃肿

属性配置

cherno 有个视频是在 window 设置 c++ 的视频,建立 c++ VS 项目的最好方式,会介绍配置

  1. 通用 -> 属性管理器 -> 活动解决方案平台,直接把 x86 删掉,因为 32 位的系统很少人用了

  2. 同理把下面的,项目上下文 -> 平台下拉框,把 Win32 删掉

  3. 通用 -> 配置类型,.exe 可执行文件改成 .dll 动态链接文件

  4. 这个 engine.dll 文件将会输出到解决方案目录下的 bin 文件夹,通过文件的类型存储到对应文件夹,文件夹名字为 “Release/Debug - 平台(x64)”,再放到 Hazel 文件夹下面
    在这里插入图片描述

  5. 中间目录就是 VS 创建的所有文件(比如 obj 文件)将会输出到的地方,所以最好还是使用一个区别于输出目录 bin 的文件夹 bin-int,这样你完全可以把 bin-int 给删掉,因为我们自己实现的部分全部在 bin 文件夹

  6. 在解决方案内(注意不是 Hazel )创建一个游戏 Sandbox 使用 Hazel,重复一遍 Hazel 的配置项设置,区别在于 Sandbox 是一个可执行文件 .exe,并设置为启动项目

    这里有个小技巧,当打开某个项目的属性面板时,直接双击别的项目,也会打开该项目的属性面板

  7. 使用 vscode 打开 sln 文件,把 Sandbox 改成第一项,这样别人从 github 克隆下来打开解决方案时,也能以 Sandbox 为启动项目

    本地的启动项目为 Sandbox 被记录在 .vs 文件中,.vs 文件一般不会上传到 github

  8. 给 Sandbox 添加 Hazel 的引用,打开 Sandbox 属性 -> 链接器 -> 命令行 -> Debug 配置,和视频中的不一样,我这里没有 Hazel.lib 文件
    在这里插入图片描述
    但是在解决方案面板中可以看到是有的
    在这里插入图片描述

    这里解释为什么我们设置生成的文件是 .dll,但视频中链接的确是 .lib 文件,因为 VS 编译 dll 文件时,会生成 lib 文件,包含了 dll 中所有函数

  9. 折叠 Hazel 所有的文件,创建我们需要的 src 文件夹,Sandbox 同理。这个显示所有文件的功能好神奇,要么显示 src 文件夹,要么显示初始化的所有文件夹

  10. 这个时候可以看到 bin 路径下已经有了 dll 文件,需要说明的是,实际运行代码的是 dll 文件,lib 文件会被链接到 Sandbox 中,这样就知道有哪些函数可以用以及这些函数在 dll 文件的什么地方
    在这里插入图片描述

  11. Sandbox 中引入命名空间后,执行 Hazel::Print(),编译不会出错,但直接执行会导致 dll 文件缺失,这种问题怎么解决?其实有自动化的方法,也可以直接把 dll 文件复制到 Sandbox.exe 同目录下

EntryPoint 入口

除非是静态链接库,其他都有入口,包括动态链接库

  1. 将析构方法 ~Appliaction() 变为虚函数,因为这个类会被(Sandbox)继承

    1. 支持多态
    2. 确保基类指针创建的派生类对象调用对应的析构函数时,正确释放内存
  2. 因为 __declspec(dllexport) 只在 Win 中被使用,所以定义一个宏限定 Win 使用,这个宏需要在解决方案的配置项内设置:c/c++ -> 预处理器 -> 预处理器定义 HZ_PLATFORM_WINDOWS;HZ_BUILD_DLL。并且需要注意的是,这里应该设置为 Debug 配置时候定义宏, 映射到 __declspec(dllexport),而 Release 没有,映射宏为 __declspec(dllimport)

  3. 为什么 Hazel::CreateApplication() 要在客户端定义,并且定义在类 Sandbox 的外面,而不是直接定义为 public 内?

  4. extern 是怎么找到外部的 Hazel::CreateApplication() 的?这里的 extern 只是告诉该文件后文出现 CreateApplicaiton() 的地方,该函数是外部定义的

  5. 目前 EntryPoint.h 文件中有标红,但是执行成功,这个不用管吗?extern 的作用就是把其后的所有内容在项目中找到相似的实现并引用
    在这里插入图片描述
    很神奇的是,在 EntryPoint.h 的 main 函数测试部分添加 printf(“Hello”) (需要在 Hazel.h 中添加 stdio.h 头文件),执行成功再把测试部分删除后,不标红了

  6. 使用 git 不一定用 git bash,可以直接再资源管理器里面用 cmd

  7. alt + d 是资源管理器的搜索栏快捷键

  8. .gitignore 中 # 表示注释,.vs/ 可以无视 .vs 文件夹,*.user 可以无视 .user 后缀的文件 (.user 无法无视 Hazel.vcxproj.user 文件)

  9. git reset . 退回到上一步

  10. 我的 github 默认主分支是 main,不是 master

  11. git add . 和 git add * 的区别是什么

  12. cherno 用的是 git push origin master,但是我的 github 默认主分支是 main,所以我使用 git push origin main

Logging Library 日志记录

记录所有的信息,比如启动信息,系统的信息,文件是否被打开,着色器是否成功编译,引擎正在做哪些事情
错误是红色,警告是黄色,普通信息是绿色,不重要信息是灰色

重点是格式化数据,比如有时候要打印对象,有时候打印数字,字符串,并且参数可能不定

  1. 使用 git submodule add https://github.com/gabime/spdlog Hazel/vendor/spdlog 将外部依赖库 spdlog 作为子模块导入到主仓库 Hazel/vendor/spdlog 文件夹下,可以保证主仓库和子模块仓库的独立性

  2. 因为 Logging 需要在所有项目中都能使用,所以把 spdlog 第三方依赖的 include 文件夹路径名添加到 “所有配置” 的附加包目录中去
    在这里插入图片描述

  3. 解决方案中左上角显示 “挂起的编辑” 是什么意思
    在这里插入图片描述

  4. inline 什么作用?内联函数,用于降低程序的运行时间,编译期间把函数体复制到函数调用处,减少函数调用时候入栈出栈的开销,适合函数不超过10行 (相比于宏,多了类型检查等好处)

  5. Log.cpp 调用的 s_CoreLogger 和 s_ClientLogger 是 Log.h 文件内的 static 标注的变量吗?是的,在 .cpp 文件相当于声明有这个变量,动态链接库会帮忙链接两个变量 (ctrl + 左键能跳转到 static 位置)

  6. 只是修改了头文件,就不需要更换 dll 文件,那么 dll 文件应该是只包含了 .cpp 文件

premake 构建系统

修改项目操作:

  1. 修改完代码后保存文件
  2. 到工程文件根目录,双击 GenerateProject.bat 脚本
  3. 进入到 VS,会弹窗口,直接全部重新加载
  4. 按 F5 即可正常运行
  1. kind “SharedLib” 表示项目是 dll,在 premake 中,共享库和动态库相同

  2. ** 表示递归搜索文件

  3. cfg: configuration 配置

  4. files 表示要包含的所有的文件列表

  5. include 用于包含头文件,相当于附加包含目录

  6. filter 过滤器,只考虑 windows 的情况,

  7. cppdialect 设置语言版本

  8. staticruntime, 连接运行时库有关,我们希望静态连接

  9. systemVersion win SDK版本

  10. postbuildcommands 从配置中复制构建目标的相对路径

  11. 根据最新的 premake5 的文档修改的代码,两种方式都可以

    -- 编译好后移动Hazel.dll文件到Sandbox文件夹下
    postbuildcommands{
    	("{COPY} %{cfg.buildtarget.relpath} ../bin/".. outputdir .."/Sandbox/")
    	--("{COPY} %{cfg.buildtarget.relpath} \"../bin/".. outputdir .."/Sandbox/\"")
    }
    
  12. 如何运行 premake.lua ?

  13. 从官网下载下来的 premake 文件夹有很多 dll 文件,但是如果删了之后好像也能运行
    在这里插入图片描述
    这样也可以
    在这里插入图片描述

事件系统

  1. 可以处理窗口事件,比如:关闭窗口、调整窗口大小、鼠标键盘输入事件
  2. 如果要做一个渲染器,没有事件系统也没问题。但是对于一个引擎来讲,是可视化创作工具,需要很多设计功能,鼠标键盘就能操作,比如一个可以通过鼠标键盘或其他工具移动的相机。
  3. 自定义事件是立即处理事件,没有缓冲事件
    缓冲事件:键盘 A 一直按,第一个A输出后,停顿一下再一直输出
  4. 事件都是阻塞事件,意味着没有被缓冲,事件没有被延迟。只要发生,比如鼠标被点击,那么整个应用会停止,优先调度(get dispatched)点击事件。

    区别于更加复杂也更优秀的过程:先从事件中获取信息,再推送到某个队列或某个缓冲区,这会产生延迟的现象,直到真正处理该事件。例如像传递、或者通过某事件总线之类的方式传递。

事件系统(下)_实现

目的是让 Application 创建一个窗口 Window,并且 Window 不会知道 Application 的信息,所以 Application 在创建窗口的时候需要创建一个 callback。
https://blog.csdn.net/alexhu2010q/article/details/106942099

  1. 整个工程文件的入口是 EntryPoint.h,里面直接有 main 函数的实现,应该是属性的配置中设置为该文件为入口

  2. 之前是写了 Event.h 文件,现在直接跟着帖子继续下去

  3. c++ 中 class 后面跟着两个变量名,分别表示什么意思,比如:class HAZEL_API Application {}

    宏 HAZEL_API 在我的工程中被映射为 __declspec(dllexport),表示要将 Application 导入 dll 文件内,其他文件可以链接到该类。这个关键字可以保证类能够在多文件内共享

  4. 创建一个 Events 文件夹,包含有 Event.h、KeyEvent.h、MouseEvent.h、Application.h 头文件,其中以 Event.h 为主,是整个事件系统的主要文件,其他三个作为不同的事件独立

  5. 需要确定的是事件系统的接口是啥?如果要自己创建一个事件,需要做什么?

  6. 包含的如 standard.h 这样的原生 c++ 文件应该包含在预编译头文件中,甚至于应该包含在 Core.h 文件中

  7. 事件系统是阻塞型事件,前面说过,不像是从事件中获取信息,将其推送到某个队列缓冲区,没有事件总线一样的东西进行传递

  • Event:作为事件的基类,最基本的接口有:获取该事件的类型GetEventType(); 获取该事件的名字 GetName();同时还可以有一个 ToString() 函数方便打印一些消息
  1. EventType: 将事件的类型写成 enum 形式,当需要在运行时候获取到事件的类型名字时,就不用使用 dynamic_cast 之类的函数
  2. EventCategory: 事件的类型 enum 形式用于过滤掉某些事件,比如说:Application 类会接受所有的事件,但是只关心键盘事件或鼠标事件

    EventType 关注的是某个具体的鼠标事件,EventCategory 表示一种类型,某些时候需要所有的鼠标类型表述
    也是一个位字段,BIT(),这个函数是宏定义在 Core.h,#define BIT(x) (1 << x) ,左移1位,相当于 2 x 2^x 2x
    目的:让它不局限于 0 1 2 3 4,因为一个事件可以分成多个分类,比如:键盘、鼠标和鼠标按钮事件都是输入事件 EventCategoryInput,而鼠标按钮事件又是 EventCategoryMouse 事件。创建一个位字段,就可以设置多个位,简单取掩码,看看什么样的分类和事件,或者一个事件属于什么分类
    那为什么 EventType 没有写

  3. m_Handler: 表示这个事件是否被处理,调度事件去处理不同的层时,不想让事件进一步传递。比如:屏幕上有一个按钮,点击了鼠标,鼠标落在按钮的范围内,事件就被处理。这个时候游戏世界并没有收到点击事件,因为按钮已经被处理过了,m_Handler 就是说明按钮是否被处理
  4. IsInCategory() 是非常简单的工具函数,判断事件是否在给定的 EventCategory 中,用于快速过滤某些事件,只需要对实际分类按位于运算,返回这个 bool 值即可
  5. GetName() 暂时设置为空:一般不会去检索一个事件名称
  6. ToString() 只是用于调试,纯虚函数必须实现,默认返回事件的名称,如果要打印更多信息,直接在函数内添加即可

KeyEvent: 重点

  1. KeyPressedEvent(int keycode, int repeatCount) : KeyEvent(keycode), m_repeatCount(repeatCount) {} 这句话里面的 KeyEvent(keycode) 什么意思,是给哪个变量初始化?是不是调用 KeyEvent 构造函数之后,也会生成一个 m_KeyCode 变量
  2. KeyEvent 的构造函数被放在 protected 内,说明其他类不能构造,只有派生类可以
  3. 对于构造函数中的 repeatCount 是有必要的,防止有时候按下一个键,会触发两次按键事件
  4. 宏定义 #define const char* GetName(x) { return #x; },就是将 x 转化为字符串字面量并返回
  5. GetStaticType() 获取静态类型,有需求是在运行时候能够知道是什么类型,那么不想先实例化一个 KeyPressedEvent 之后,再调用 GetEventType(),所以获取类型最好作为静态函数
    1. 在 EventDispatcher 类中使用,作为调度器,需要检查所有的待处理事件,只有当待处理事件满足目标事件类型,才应该放到待执行列表中等待执行
  6. using EventFn = std::function<bool(T&)>; 这句话,function() 的作用是啥
    1. function() 是一个模板类,可调用一切可调用的实体(lambda 函数、函数指针、函数对象等)
    2. 这句话内,EventFn 是一个类型别名,定义了一个 function 对象
    3. function 对象接受以 T& 参数,返回 bool 值的一个函数
    4. 这里的 T 是模板类型
    5. 这里的 function() 能作为一个接口,存储任何返回 bool 值并接受一个 T& 类型引用作为参数的函数。这样调用者就不用关心函数的实现细节,直接调用。
    6. function 在回调机制、事件驱动编程和泛型编程中作用很大
  7. m_Event.m_Handled = func(*(T*)&m_Event); 这句意思是无论 func 是什么函数,只要返回值是 bool,参数是 T& 类型,那么这个函数在此处都会被调用
  8. 更新、渲染、时钟函数都有对应的事件类,可以以事件的形式传播
  9. 重载的输出流符号作用于日志库,能更方便调用事件的 ToString(),记录事件
  10. HZ_TRACE(e); Application.cpp 文件中运行这句话,因为已经重载过了输出流符号
  11. 必须添加头文件 #include "spdlog/fmt/ostr.h" spd 的输出流操作符,这样就可以自定义输出类型

预编译头

就是一个头文件,源文件添加后可以避免某些头文件被反复编译

  1. hapch.cpp 本来是不需要的,但是 VS 会自动生成
  2. 在 premake.lua 中添加 pchheader “hzpch.h” 和 pchsource “Hazel/src/hzpch.cpp”,后者只有 VS 需要,其他 IDE 会无视。其中,前面那句效果相当于把所有包含了 hzpch.h 的文件属性中预编译头设置为 “使用”,而后面那句效果相当于把 hzpch.cpp 文件属性中的预编译头设置为 “创建”
  3. 再次 Build 工程后,项目配置会提醒是否使用 pch
  4. 之后再所有的 .cpp 文件中包含 hzpch.h (实际上没有使用的 cpp 文件也需要添加)
  5. 需要有一个 hzpch.cpp 文件,告诉编译器把 hzpch.h 预编译头文件的内容全部编译完 (因为 VS 的编译系统以一个个文件为单位,当一个文件发生修改,那么所有文件都会被重新编译,所以把一些不太变动的文件放在预编译头文件中,告诉编译器提前编译好,之后就不会改变,提升编译效率)

技巧

Git

  1. 使用 git 不一定用 git bash,可以直接再资源管理器里面用 cmd
  2. alt + d 是资源管理器的搜索栏快捷键
  3. .gitignore 中 # 表示注释,.vs/ 可以无视 .vs 文件夹,*.user 可以无视 .user 后缀的文件 (.user 无法无视 Hazel.vcxproj.user 文件)
  4. git reset . 退回到上一步
  5. 我的 github 默认主分支是 main,不是 master
  6. git add . 和 git add * 的区别是什么? git add . 会忽略 .gitignore 的文件,但是 git add * 不会
  7. cherno 用的是 git push origin master,但是我的 github 默认主分支是 main,所以我使用 git push origin main
  8. 如何回退到上一版本:git reset --hard HEAD^
  9. 撤回回退:git reflog 查看历史命令,要回退到哪个版本
    git reset --hard 版本号
  10. 撤回 commit 和 add .: git reset (--mixed) HEAD^,括号里的可有可无
  11. 撤销 git add . :git reset . 即可
  12. github 上的版本如何回滚,网页版是没有回滚操作的,只有 Github For Win 客户端有,如果想在网页端操作,可以先按照这个教程 https://blog.csdn.net/weixin_44259720/article/details/112608864 创建一个新的分支,之后把默认分支换成新的分支,同时改名成功,并且把不想要的分支都删掉。这种操作可以在新分支的 Activity 中见到操作记录,但已经是比较好的解决方案。
  13. 所以必须在 push to github 之前查阅将会出现的变化,仔细核对,否则推送到 github 后非常麻烦。或者可以fetch到一个地方之后,再推送到 main 版本
  14. 需要知道 push 哪些文件,是必须的,哪些文件不是必须的,尽量保证 github 仓库中文件的干净程度?可以新建一个分支,先推送试试,如果clone下来发现无法正常运行,可以再尝试?
  15. 首先 bin/ 和 bin-int/ 是编译的结果,可以不 push 到 github;.sln 文件也不需要;.vcxproj 等文件也不需要
  16. .gitignore 只能忽视原来没有被跟踪的文件,如果要解除跟踪,使用 git rm --cached <file>。比如这里需要 git rm --cached *.sln这样能把 .sln 文件给解除跟踪
  17. 提交规范
    feat: 新功能、新特性
    fix: 修改 bug
    perf: 更改代码,以提高性能(在不影响代码内部行为的前提下,对程序性能进行优化)
    refactor: 代码重构(重构,在不影响代码内部行为、功能下的代码修改)
    docs: 文档修改
    style: 代码格式修改, 注意不是 css 修改(例如分号修改)
    test: 测试用例新增、修改
    build: 影响项目构建或依赖项修改

VS

  1. alt + 鼠标左键,竖向选中代码,用于删除代码,或者统一缩进

其他

  1. alt+d 文件资源管理器中快捷定位到路径栏,cmd 可以打开 cmd 窗口

报错

找不到头文件

为什么引用头文件说找不到?改成双引号就行 “Test.h”
在这里插入图片描述
第二种方法,想要引用头文件可以用尖括号 <>,可以进入属性配置面板:c/c++ -> 常规 -> 附加包含目录输入 $(SolutionDir)Hazel\src

<> 头文件会去系统目录寻找,“” 先找项目目录,再找系统目录

Sandbox.exe 无法找到入口

因为 dll 文件没有更新,去把最新的 dll 文件更新下就行,最新的 dll 文件需要看引擎的 dll 文件输出到哪里,从配置属性"常规"里面可以看到
在这里插入图片描述

报错窗口乱码怎么解决,同时报错的窗口英文字母也是乱码怎么解决

inconsistent dll linkage 不一致的 dll 链接

可能是 dll 链接拼写错误
“配置属性面板 -> c/c++ -> 预处理器”
看看里面的宏有没有拼写错误导致 dll 链接失败

error LNK2019: 无法解析的外部符号 & fatal error LNK1120: 1 个无法解析的外部命令

SandboxApp.obj : error LNK2019: 无法解析的外部符号 "class Hazel::Application * __cdecl Hazel::CreateApplication(void)" (?CreateApplication@Hazel@@YAPEAVApplication@1@XZ),函数 main 中引用了该符号
这里是 main 函数中引用的外部引用 extern CreateApplication() 无法解析
extern Hazel::Application* Hazel::CreateApplication();
查看实现 CreateApplication 的文件 Sandbox.cpp 中,发现未添加命名空间
在这里插入图片描述
改为 Hazel::Application* Hazel::CreateApplication() 即可

error LNK2019: 无法解析的外部符号,函数 main 中引用了该符号

error LNK2019: 无法解析的外部符号 "public: static void __cdecl Hazel::Log::Init(void)" (?Init@Log@Hazel@@SAXXZ),函数 main 中引用了该符号
这里仍然是 main 函数内的链接问题,这里的 Hazel::Log::Init() 函数识别不到

  1. 检查 Log 类定义的时候是否添加命名空间
  2. 检查 Log 定义的时候有没有添加 __declspec(dllexport),必须添加字段表示将类导入 dll
    在这里插入图片描述
    我犯了第二个错误
    更改为 class HAZEL_API Log 即可(宏 HAZEL_API 在我的工程中被映射为 __declspec(dllexport))

git push origin main报错 连接不到 443

Failed to connec t to github.com port 443 after 21083 ms: Couldn't connect to server
首先看下 clash pro 的请求日志 Logs,发现都能正常访问
于是重新 git push,弹出窗口要验证码,选择网页验证,输入身份验证器中的号码即可
在这里插入图片描述

git 拉取超时

git submodule add 拉取超时
因为拉取的包太大了
有两种错误提示

  • error: RPC failed; curl 18 HTTP/2 stream 5 was reset09.00 KiB/s
  • fetch-pack: unexpected disconnect while reading sideband packet

把命令改成
git submodule add --depth 1 https://github.com/gabime/spdlog Hazel/vendor/spdlog 添加关键字 ‘–depth 1’,表示只拉取最新一次更新

error C2597: 对非静态成员的非法引用

error C2597: 对非静态成员“Hazel::Log::s_CoreLogger”的非法引用
那就是说明 s_CoreLogger 是非静态成员,但是用成了静态成员,比如说 static 函数的返回值是 s_CoreLogger&,那么就出现错误,static 函数必须返回 static 成员
在这里插入图片描述

error C2039: “stdout_color_mt”: 不是 “spdlog” 的成员

spdlog::stdout_color_mt 这么些报错
是因为没有包含定义 stdout_color_mt 的头文件,这个头文件定义 stdout_color_mt 应该也是定义在 spdlog 这个命名空间内

error C2040: 间接寻址级别不同

error C2040: “s_CoreLogger”:“std::shared_ptr<spdlog::logger>”与“std::shared_ptr<spdlog::logger> &”的间接寻址级别不同
在 Log.cpp 中声明了 Log.h 的变量,但是没有保持两个变量相同内容,.h 中是引用,.cpp 中是变量

这里不要被 .h 文件上面的 public 函数误导,那是公开给别的对象的函数,返回的是引用
在这里插入图片描述
在这里插入图片描述

弹窗报错:Sandbox.exe 无法找到入口

无法定位程序输入点 Hazel::Log::Init() ,在动态链接库上
还是 dll 链接的问题,我这里是没有更新 dll 文件
在这里插入图片描述

No Premake script (premake5.lua) found!

必须命名 premake 文件为 premake5.lua
注意把当前 vs 打开的 premake.lua 文件关闭,重命名之后再打开,否则在 vs 修改的记录按 ctr + s 后,vs 会保存一个 premake.lua 文件到原位置,premake5.lua 的内容不会改变

Error: [string “src/base/api.lua”]:606: bad argument #2 to ‘deferredjoin’ (string expected, got table)

https://github.com/premake/premake-core/issues/1858

error MSB3191: 无法创建目录,因为同名文件或目录已存在。

error MSB3191: 无法创建目录“..\bin\Debug-windows-x86_64\Sandbox\”。无法创建“D:\Projects\Hazel\Hazel\bin\Debug-windows-x86_64\Sandbox”,因为同名文件或目录已存在。
把 {COPY} 改成 {COPYFILE} 不知道为啥报错

-- 编译好后移动Hazel.dll文件到Sandbox文件夹下
postbuildcommands{
	("{COPYFILE} %{cfg.buildtarget.relpath} ../bin/" .. outputdir .. "/Sandbox")
}

在这里插入图片描述
https://github.com/TheCherno/Hazel/issues/623
复制这个答主的就好了,真他妈高血压

error MSB3073

error MSB3073: 命令“IF EXIST ..\bin\Debug-windows-x86_64\Hazel\Hazel.dll\ (xcopy /Q /E /Y /I ..\bin\Debug-windows-x86_64\Hazel\Hazel.dll ..\bin\Debug-windows-x86_64\Sandbox > nul) ELSE (xcopy /Q /Y /I ..\bin\Debug-windows-x86_64\Hazel\Hazel.dll ..\bin\Debug-windows-x86_64\Sandbox > nul)
再点一次 F5 就可以了

把 Hazel 的 dll 文件复制到 Sandbox 里面发现可以,其实就是一开始检测目录发现是空文件,如果再按一次 F5 再次运行时候,就能检测到存在的文件
https://github.com/TheCherno/Hazel/issues/9

error MSB3073: 命令“copy /B /Y ..\bin\Debug-windows-x86_64\Hazel\Hazel.dll "\bin\Debug-windows-x86_64\Sandbox"
继续报错,不是引号的问题,如果在 cmd 中是可以复制成功的
现在我想知道,执行 copy 的这条语句是在哪里

error MSB3073: 命令“copy /B /Y "..\..\bin\Debug-windows-x86_64\Hazel\Hazel.dll" "..\..\bin\Debug-windows-x86_64\Sandbox\"
退回两层去找 bin,可能是 Hazel/src,但如果是这里,这句命令可以执行成功(cmd 中可以)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/881428.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

笔记整理—内核!启动!—linux应用编程、网络编程部分(2)linux的文件管理策略

关于硬盘中的静态文件与inode&#xff1a;例如文件存储在扇区中&#xff0c;一个文件占用10个字节&#xff0c;一个扇区为512字节&#xff0c;这样的情况下一个扇区就只放了一个实际为10字节的文件&#xff0c;余下的502字节不可存放其他文件&#xff0c;因为扇区已经是可以访问…

机器学习 | Scikit Learn中的普通最小二乘法和岭回归

在统计建模中&#xff0c;普通最小二乘法&#xff08;OLS&#xff09;和岭回归是两种广泛使用的线性回归分析技术。OLS是一种传统的方法&#xff0c;它通过最小化预测值和实际值之间的平方误差之和来找到数据的最佳拟合线。然而&#xff0c;OLS可以遭受高方差和过拟合时&#x…

基于PHP的电脑线上销售系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于phpMySQL的电脑线上销售系…

【C语言】自定义类型——联合和枚举

目录 一、联合体&#xff08;共用体&#xff09; &#xff08;1&#xff09;联合体类型的声明 &#xff08;2&#xff09;联合体类型的特点 &#xff08;3&#xff09;联合体和结构体的比较 &#xff08;4&#xff09;联合体大小的计算 &#xff08;5&#xff09;联合体的…

RK3588/RK3588s运行yolov8达到27ms

前言 Hello&#xff0c;小伙伴们~~我最近做了一个比较有意思的东西&#xff0c;想起来也好久没有写博客了&#xff0c;就记录一下吧。希望和大家一起学习&#xff0c;一起进步&#xff01; 我简单介绍一下我最近做的这个东西的经过哈~上个月在B站上看到了一个博主发了一条视频关…

Qt 模型视图(四):代理类QAbstractItemDelegate

文章目录 Qt 模型视图(四):代理类QAbstractItemDelegate1.基本概念1.1.使用现有代理1.2.一个简单的代理 2.提供编辑器3.向模型提交数据4.更新编辑器的几何图形5.编辑提示 Qt 模型视图(四):代理类QAbstractItemDelegate ​ 模型/视图结构是一种将数据存储和界面展示分离的编程方…

Docker笔记-容器数据卷

Docker笔记-容器数据卷 docker的理念将运行的环境打包形成容器运行&#xff0c;运行可以伴随容器&#xff0c;但是我们对数据的要求是希望持久化&#xff0c;容器 之间可以共享数据&#xff0c;Docker容器产生的数据&#xff0c;如果不通过docker commit生成新的镜像&#xf…

assign是赋值,不是连接

如下图是一个top文件的背压 如果把原本应该是外界输入的变量m_ip_hdr_ready通过phv_parser_hdr_ready来“赋值&#xff01;&#xff01;&#xff01;”&#xff0c;那么模块内部本该有的ready信号&#xff0c;就会是Z高阻态&#xff0c;因为没有给到值。 正确的赋值 将整个模…

【医疗大数据】医疗保健领域的大数据管理:采用挑战和影响

选自期刊**《International Journal of Information Management》**&#xff08;IF:21.0) 医疗保健领域的大数据管理&#xff1a;采用挑战和影响 1、研究背景 本研究的目标是调查阻止医疗机构实施成功大数据系统的组织障碍&#xff0c;识别和评估这些障碍&#xff0c;并为管理…

微信小程序拨打电话点取消报错“errMsg“:“makePhoneCall:fail cancel“

问题&#xff1a;微信小程序中拨打电话点取消&#xff0c;控制台报错"errMsg":"makePhoneCall:fail cancel" 解决方法&#xff1a;在后面加上catch就可以解决这个报错 wx.makePhoneCall({phoneNumber: 181********}).catch((e) > {console.log(e) //用…

调整pycharm中的字体大小

1.找到设置 2.打开setting &#xff0c;按照图示操作即可

YOLOv5白皮书-第Y1周:调用官方权重进行检测

>- **&#x1f368; 本文为[&#x1f517;365天深度学习训练营](小团体&#xff5e;第八波) 中的学习记录博客** >- **&#x1f356; 原作者&#xff1a;[K同学啊](K同学啊-CSDN博客)** 一、前言 拖了好久&#xff0c;终于要开始目标检测系列了。自己想过好几次&#xf…

中秋节特别游戏:给玉兔投喂月饼

&#x1f5bc;️ 效果展示 &#x1f4dc; 游戏背景 在中秋这个充满诗意的节日里&#xff0c;玉兔因为贪玩被赶下人间。在这个温柔的夜晚&#xff0c;我们希望通过一个小游戏&#xff0c;让玉兔感受到人间的温暖和关怀。&#x1f430;&#x1f319; &#x1f3ae; 游戏设计 人…

Broadcast:Android中实现组件及进程间通信

目录 一&#xff0c;Broadcast和BroadcastReceiver 1&#xff0c;简介 2&#xff0c;广播使用 二&#xff0c;静态注册和动态注册 三&#xff0c;无序广播和有序广播 1&#xff0c;有序广播的使用 2&#xff0c;有序广播的截断 3&#xff0c;有序广播的信息传递 四&am…

[产品管理-15]:NPDP新产品开发 - 13 - 产品创新流程 - 具体产品的创新流程:精益生产与敏捷开发

目录 前言&#xff1a;​ 一、集成产品开发IPD模型——集成跨功能团队的产品开发 1.1 概述 1、IPD模型的核心思想 2、IPD模型的主要组成部分 3、IPD模型的实施步骤 4、IPD模型的优点 1.2 基于IPD系统的组织实践等级 1.3 IPD的优缺点 二、瀑布开发模型 1、定义与特点…

21、Tomato

难度 低(个人认为中) 目标 root权限 一个flag 使用VMware启动 kali 192.168.152.56 靶机 192.168.152.66 信息收集 端口信息收集 可以看到有个ftp服务&#xff0c;2211实际是ssh协议端口&#xff0c;80、8888是一个web服务 web测试 80端口显示一个tomato 查看源码给了一些…

opencv图像透视处理

引言 在图像处理与计算机视觉领域&#xff0c;透视变换&#xff08;Perspective Transformation&#xff09;是一种重要的图像校正技术&#xff0c;它允许我们根据图像中已知的四个点&#xff08;通常是矩形的四个角&#xff09;和目标位置的四个点&#xff0c;将图像从一个视…

软件安装攻略:EmEditor编辑器下载安装与使用

EmEditor是一款在Windows平台上运行的文字编辑程序。EmEditor以运作轻巧、敏捷而又功能强大、丰富著称&#xff0c;得到许多用户的好评。Windows内建的记事本程式由于功能太过单薄&#xff0c;所以有不少用户直接以EmEditor取代&#xff0c;emeditor是一个跨平台的文本编辑器&a…

聊城网站建设:企业如何打造高效官网

聊城网站建设&#xff1a;企业如何打造高效官网 在互联网飞速发展的今天&#xff0c;官方网站已成为企业展示形象、推广产品、与客户沟通的重要平台。尤其对于聊城地区的企业来说&#xff0c;建立一个高效的官网显得尤为重要。本文将分享一些关键步骤&#xff0c;帮助企业打造一…

MapReduce基本原理

目录 整体执行流程​ Map端执行流程 Reduce端执行流程 Shuffle执行流程 整体执行流程 八部曲 读取数据--> 定义map --> 分区 --> 排序 --> 规约 --> 分组 --> 定义reduce --> 输出数据 首先将文件进行切片&#xff08;block&#xff09;处理&#xff…