Hazel游戏引擎(005)
本人菜鸟,文中若有代码、术语等错误,欢迎指正
我写的项目地址:https://github.com/liujianjie/GameEngineLightWeight(中文的注释适合中国人的你)
文章目录
- 前言
- 关键操作
- 代码文件+关键代码+代码流程
- 代码文件
- 关键代码
- extern外部定义CreateApplication
- 包含头文件+条件编译和宏定义实现Dll导入与导出
- 代码流程
- 运行效果
- Github
- 涉及的C++知识
前言
-
此节目的
将上一小节的main函数入口点写在Hazel项目中,由引擎内部控制。
优化dll导出导入代码,用条件编译+宏定义来编写dll导出与导入代码
-
Cherno本节完整代码链接
https://github.com/TheCherno/Hazel/commit/f9fbbd2bf3d870a6586c5c4f70a867d78e27b113
关键操作
-
Hzel项目
右键属性(所有配置)=>C/C++=>预处理器=>预处理器定义
输入
HZ_PLATFORM_WINDOWS;HZ_BUILD_DLL
-
Sandbox项目
-
右键属性(所有配置)=>C/C++=>预处理器=>预处理器定义
输入
HZ_PLATFORM_WINDOWS;
-
右键属性(所有配置)=>C/C++=>常规=>附加包含目录
输入
$(SolutionDir)Hazel\src
为了Sandbox项目能引入Hazel项目的文件
#include <Hazel.h>
-
代码文件+关键代码+代码流程
代码文件
-
Hazel项目
-
Application类
引擎内部功能实现
-
Core.h
来根据不同项目的条件编译,而写dll导入还是导出的宏定义
-
EntryPoint.h
入口点,main函数
-
Hazel.h
引入其它头文件,控制给Sandbox项目提供哪些引擎内部功能
-
-
Sandbox项目
-
SanboxApp.cpp
应用层实现
-
关键代码
extern外部定义CreateApplication
-
在Hazel项目的Application.h中
namespace Hazel {class HAZEL_API Application{....};// To be defined in CLIENTApplication* CreateApplication(); }在Hazel命名空间内声明了CreateApplication函数
-
在Sandbox项目的SandboxApp.cpp中
Hazel::Application* Hazel::CreateApplication() {return new Sandbox(); }定义了CreateApplication函数
-
在EntryPoint.h中调用
extern Hazel::Application* Hazel::CreateApplication(); int main(int argc, char** argv){auto app = Hazel::CreateApplication();... }将CreateApplication函数声明为extern,表示此函数会在外部定义,接下来使用的这函数时将使用在外部定义的CreateApplication
包含头文件+条件编译和宏定义实现Dll导入与导出
-
在Core.h中
#pragma once #ifdef HZ_PLATFORM_WINDOWS#ifdef HZ_BUILD_DLL#define HAZEL_API __declspec(dllexport)#else#define HAZEL_API __declspec(dllimport)#endif #else#error Hazel only supports Windows! #endif根据条件编译定义HAZEL_API是dll导入还是导出,由上的关键操作小点可知Hazel项目将是__declspec(dllexport),Sandbox项目是__declspec(dllimport)
-
问题在于:这关Sandbox项目何事,这明明是Hazel项目中的头文件
由于Sandbox#include <Hazel.h>,而Hazel项目的Hazel.h包含了Application.h,Application.h又包含了Core.h文件,
所以这Core.h的代码也会被拷贝到Sandbox项目的SandboxApp.cpp中#include <Hazel.h>的位置,
并且Application.h也会被拷贝到<Hazel.h>的位置。
#include <Hazel.h> class Sandbox : public Hazel::Application { public:Sandbox(){}~Sandbox(){} }; .....所以Sandbox项目也有HAZEL_API宏定义,且是__declspec(dllimport)
-
所以SandboxApp.cpp的代码将变成
#pragma once #ifdef HZ_PLATFORM_WINDOWS#ifdef HZ_BUILD_DLL#define HAZEL_API __declspec(dllexport)#else#define HAZEL_API __declspec(dllimport)#endif #else#error Hazel only supports Windows! #endif namespace Hazel {class HAZEL_API Application// HAZEL_API被替换成__declspec(dllimport){public:Application();virtual ~Application();void Run();};// To be defined in CLIENTApplication* CreateApplication(); } ....省略EntryPoint.h的代码(下面将运行流程会有).... class Sandbox : public Hazel::Application { public:Sandbox(){}~Sandbox(){} }; .....所以Sandbox类导入了dll中的Application类,且可以继承Application。
对应003节的代码
#pragma once namespace Hazel {_declspec(dllexport) void Print();// 导出 }namespace Hazel {_declspec(dllimport) void Print(); // 导入 } void main() {Hazel::Print();// 使用 }
代码流程
-
开始运行Sandbox.exe
由于Sandbox中#include <Hazel.h>,而Hazel项目的Hazel.h包含了Application.h和EntryPoint.h入口文件
Hazel.h
#pragma once // For use by Hazel applications #include <iostream> #include "Hazel/Application.h" // ---Entry Point--------------------- #include "Hazel/EntryPoint.h" // ----------------------------------- -
EntryPoint.h定义了main函数,即写了入口点,所以程序会在这运行
因为SandboxApp.cpp在第一行包含Hazel.h,Hazel.h又包含EntryPoint.h,那么EntryPoint.h的代码会被拷贝到SandboxApp.cpp中
#include <Hazel.h>将拥有以下EntryPoint.h中的代码
#pragma once #ifdef HZ_PLATFORM_WINDOWS extern Hazel::Application* Hazel::CreateApplication(); int main(int argc, char** argv) {std::cout << "Core::main" << std::endl;auto app = Hazel::CreateApplication();app->Run();delete app; } #endifmain函数中执行CreateApplication函数,将调用定义在SandboxApp.cpp中的CreateApplication函数
Hazel::Application* Hazel::CreateApplication() {return new Sandbox(); }这函数返回的指针是Hazel项目中的Application父类指针,所以auto app的类型是Application*。
-
当执行app->Run()函数时,由于Run()函数没有声明为虚函数,所以会调用Application中的Run()函数
#include "Application.h" namespace Hazel {Application::Application(){}Application::~Application(){}void Application::Run(){while (true);} }Application的Run函数是一个while循环,所以循环会无限制运行中
运行效果

需要把最新生成的Hazel.dll放在Sandbox.exe文件夹下

Github
-
.gitignore
在.git文件夹下新建.gitignore文件,可以声明一些不想提交到暂存区的文件
# Binaries **/bin/ bin-int/# Visual Studio files and folder .vs/ **.sln **.vcxproj **.vcxproj.filters **.vcxproj.user **.csproj -
其它命令
git add *// 提交文件到暂存区 git reset . // 将暂存区文件返回 git status // 查看文件有无提交到暂存区状态 git commit -m "注释"// 将暂存区的内容添加到仓库 git push origin main // 将本地的分支版本上传到远程并合并
涉及的C++知识
对应此节代码地方
Hazel::Application* Hazel::CreateApplication()
{return new Sandbox();
}
auto app = Hazel::CreateApplication();
app->Run();
转换为以下容易理解的代码
#include <iostream>
using namespace std;class Application {
public:void Run() {cout << "Application::Run()" << endl;}
};
class Sandbox : public Application {
public:void Run() {cout << "Sandbox::Run()" << endl;}
};
void main() {Application* app = new Sandbox();app->Run();// 由于Run()函数没有声明为virtual虚函数,所以执行父类的Run函数
}

相关文章:
Hazel游戏引擎(005)
本人菜鸟,文中若有代码、术语等错误,欢迎指正 我写的项目地址:https://github.com/liujianjie/GameEngineLightWeight(中文的注释适合中国人的你) 文章目录前言关键操作代码文件关键代码代码流程代码文件关键代码exter…...
牛客网Python篇数据分析习题(四)
1.现有一个Nowcoder.csv文件,它记录了牛客网的部分用户数据,包含如下字段(字段与字段之间以逗号间隔): Nowcoder_ID:用户ID Level:等级 Achievement_value:成就值 Num_of_exercise&a…...
盲盒如何创业?
所谓的“盲盒”,受众群体大部分是那些爱碰运气的人,顾客买的是那种在打开盲盒时一刹那的惊喜感和神秘感,在打开盲盒之前,谁也不知道自己会得到什么,这也是为什么消费者更愿意购买的原因。网上的盲盒,主要是…...
第1集丨Java中面向对象相关概念汇总
目录一、基本概念1.1 类1.2 属性1.3 方法1.4 静态1.5 包1.6 import二、高级概念2.1 构造方法2.2 继承2.3 super & this2.4 多态2.5 方法重载2.6 方法重写2.7 访问权限2.8 内部类2.9 final2.10 抽象2.11 接口2.12 匿名类面向对象的编程思想力图使计算机语言中对事物的描述与…...
高性能(二)
三、读写分离和分库分表 1.读写分离 1.1 概述 将数据库的读写操作分散到不同的数据库节点上 通常一主多从一台主数据库负责写,多台从数据库负责读。 主库和从库之间会进行数据同步,以保证从库中数据的准确性。 1.2 问题及解决 1.2.1 问题 主从同…...
Allegro如何实现同一个屏幕界面分屏显示操作指导
Allegro如何实现同一个屏幕界面分屏显示操作指导 在做PCB设计的时候,会需要分屏显示,比如一边是放大的视图,另外一边是缩小的视图,Allegro支持同一个屏幕界面下进行分屏显示,如下图 而且会实时同步起来 如何分屏,具体操作如下 点击View...
前后端一些下载与配置(第二篇 第10天过后)nuxt banner redis 短信服务
NUXT 应该是不用怎么装? 有现成的 axios 还需要在npm吗 好像已经有现成的了 banner banner 笔记汇总P396 Redis Linux安装redis tar -xzvf redis-6.2.6.tar.gz cd redis-6.2.6 照着他做 然后 cd /usr/local/redis/bin ./redis-server /usr/local/redis…...
OSG三维渲染引擎编程学习之四十八:“第五章:OSG场景渲染” 之 “5.6 多重纹理映射”
目录 第五章 OSG场景渲染 5.6 多重纹理映射 5.6.1 多重纹理映射介绍 5.6.2 多重纹理映射示例...
对Node.js 的理解?优缺点?应用场景?
一、是什么 Node.js 是一个开源与跨平台的 JavaScript 运行时环境 在浏览器外运行 V8 JavaScript 引擎(Google Chrome 的内核),利用事件驱动、非阻塞和异步输入输出模型等技术提高性能 可以理解为 Node.js 就是一个服务器端的、非阻塞式I/…...
Bean的生命周期
所谓的生命周期指的是一个对象从诞生到销毁的整个生命过程,我们把这个过程就叫做一个对象的生命周期~~ Bean的生命周期分为以下五大部分: 实例化(为 Bean 分配内存空间) 设置属性(Bean对象注入/装配) 初…...
Python学习-----函数2.0(函数对象,名称空间,作用域-->全局变量与局部变量)
目录 前言: 1.函数对象 (1)函数对象的引用 (2)函数可以放到序列里面 (3)函数可以作为参数 , 传递给另一个函数 2.名称空间 3.作用域 (1)作用域的理解 …...
Java中Json字符串和Java对象的互转
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。诞生于 2002 年。易于人阅读和编写。同时也易于机器解析和生成。JSON 是目前主流的前后端数据传输方式。 JSON 采用完全独立于语言的文本格式,但是也使用了类似于 C 语言家族的…...
代码随想录NO42 | 动态规划_Leetcode70. 爬楼梯 (进阶) 322. 零钱兑换 279.完全平方数
动态规划_Leetcode70. 爬楼梯 (进阶) 322. 零钱兑换 279.完全平方数70. 爬楼梯 (进阶) 在原题基础上,改为:一步一个台阶,两个台阶,三个台阶,…,直到 m个台阶…...
【C++从入门到放弃】初识C++(基础知识入门详解)
🧑💻作者: 情话0.0 📝专栏:《C从入门到放弃》 👦个人简介:一名双非编程菜鸟,在这里分享自己的编程学习笔记,欢迎大家的指正与点赞,谢谢! C基础…...
企业工程项目管理系统源码+spring cloud 系统管理+java 系统设置+二次开发
工程项目各模块及其功能点清单 一、系统管理 1、数据字典:实现对数据字典标签的增删改查操作 2、编码管理:实现对系统编码的增删改查操作 3、用户管理:管理和查看用户角色 4、菜单管理:实现对系统菜单的增删改查操…...
【GPLT 三阶题目集】L3-016 二叉搜索树的结构
二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分…...
核心交换机安全多业务高性能万兆交换机
RG-S5750-24SFP/12GT交换机是锐捷网络推出的融合了高性能、高安全、多业务的新一代三层交换机。RG-S5750-24SFP/12GT 交换机能够提供灵活的介质接口,满足网络建设中不同介质的连接需要。全千兆的端口形态,加上可扩展的高密度万兆端口,提供1&a…...
Android APK 签名打包原理分析(三)【静默安装的实现方案】
背景 小编目前从事的系统定制类工作,有客户提出了,需要后台“静默安装”他们的app,也就是悄无声息的安装,而且特别强调,不可以跳出任何安装引导页面,他们的app下载完成之后,后台调用公开的android install代码,系统就后台完成安装,安装完成之后,重新打开应用就可以。…...
mulesoft MCIA 破釜沉舟备考 2023.02.14.05
mulesoft MCIA 破釜沉舟备考 2023.02.14.05 1. Refer to the exhibit.2. A Kubernetes controller automatically adds another pod replica to the resource pool in response to increased application load.3. An XA transaction Is being configured that involves a JMS c…...
结构体的三种定义方法、结构体类型名(可选标志符)什么时候可以省略
结构体的三种定义方法 一、单独定义: 先定义结构体类型,再定义变量 定义结构体的格式如下: struct 结构体名 { 若干数据项; } ; 其中,struct为关键字; 结构体名是用户定…...
visionOS开发实战:从示例项目到空间应用构建全指南
1. 从零到一:如何高效利用 visionOS 示例项目库如果你和我一样,是个对 Apple Vision Pro 和 visionOS 开发充满好奇的开发者,那么你肯定经历过这样的阶段:面对一个全新的平台,既兴奋于其无限的可能性,又对如…...
5分钟告别百度网盘提取码烦恼:智能获取工具全解析
5分钟告别百度网盘提取码烦恼:智能获取工具全解析 【免费下载链接】baidupankey 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 你是否曾经因为一个简单的提取码,在浏览器标签页间反复切换,浪费了宝贵的十几分钟…...
【SITS2026权威前瞻】:AI研发自动化测试的5大范式跃迁与2024落地避坑指南
更多请点击: https://intelliparadigm.com 第一章:AI研发自动化测试:SITS2026专题 随着大模型驱动的研发范式演进,AI系统本身的可测试性面临全新挑战——模型行为非确定、输入空间高维、验证标准模糊。SITS2026(Softw…...
SecureVault - 基于新范式的Windows文件加密工具
前言作为一个常年和各种文件打交道的普通人,我一直有个困扰:现有的加密工具要么太复杂,要么太贵,要么用的都是几十年的老算法。我想,能不能做一款简单、便宜、但加密方式完全不同的新工具?于是就有了 Secur…...
为什么92%参会者在P3东区绕行超4分钟?2026大会停车动线算法白皮书首度披露
更多请点击: https://intelliparadigm.com 第一章:2026年AI技术大会停车指引概览 2026年AI技术大会主会场设于上海张江科学城国际会展中心,周边共开放3个智能停车场(P1–P3),全部支持车牌自动识别、无感支…...
物联网标准演进与云平台破局:从M2M到IoT的实战路径
1. 从M2M到IoT:一场迟来的标准革命十多年前,当我第一次接触“机器对机器”这个概念时,感觉它就像个被锁在工厂车间里的幽灵——功能强大,但离普通人的生活无比遥远。那时的M2M,谈论的是专用网络、私有协议和封闭的垂直…...
番茄小说下载器:打造个人专属离线小说图书馆的完整指南
番茄小说下载器:打造个人专属离线小说图书馆的完整指南 【免费下载链接】fanqienovel-downloader 下载番茄小说 项目地址: https://gitcode.com/gh_mirrors/fa/fanqienovel-downloader 你是否曾在通勤路上突然想读小说,却因为网络信号不佳而无法加…...
从苹果三星2016年困境看消费电子行业创新与供应链管理
1. 行业巨头的十字路口:苹果与三星的2016年镜像2016年,对于全球消费电子行业而言,是一个充满微妙转折的年份。站在聚光灯下的两大巨头——苹果与三星,仿佛站在了同一面镜子的两侧,映照出截然不同的困境,却又…...
【信息科学与工程学】【控制科学】第三篇 管理系统控制知识
管理系统控制知识 表K.144501 管理系统控制概述 项目 内容 定理/规律/数学方程式/集合特征/几何特征/拓扑特征/代数特征 1. 管理控制定义:控制系统S = (A, B, C, D),其中A是控制主体集合,B是被控对象集合,C是控制规则集合,D是信息流集合 2. 控制层级定理:高层战略控…...
一天2710亿Token!“爱马仕”反超“龙虾”,AI Agent进入真实用量竞争阶段
“爱马仕”登顶全球应用调用榜5月9日,Hermes Agent(昵称:爱马仕)登顶OpenRouter全球应用调用量榜首,首次超越OpenClaw(昵称:龙虾)。据OpenRouter应用Token消耗榜最新数据,…...
