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为关键字; 结构体名是用户定…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
拉力测试cuda pytorch 把 4070显卡拉满
import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
