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; } #endif
main函数中执行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为关键字; 结构体名是用户定…...

stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...

网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践
作者:吴岐诗,杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言:融合数据湖与数仓的创新之路 在数字金融时代,数据已成为金融机构的核心竞争力。杭银消费金…...
苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会
在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...

【Veristand】Veristand环境安装教程-Linux RT / Windows
首先声明,此教程是针对Simulink编译模型并导入Veristand中编写的,同时需要注意的是老用户编译可能用的是Veristand Model Framework,那个是历史版本,且NI不会再维护,新版本编译支持为VeriStand Model Generation Suppo…...

五子棋测试用例
一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏,有着深厚的文化底蕴。通过将五子棋制作成网页游戏,可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家,都可以通过网页五子棋感受到东方棋类…...
绕过 Xcode?使用 Appuploader和主流工具实现 iOS 上架自动化
iOS 应用的发布流程一直是开发链路中最“苹果味”的环节:强依赖 Xcode、必须使用 macOS、各种证书和描述文件配置……对很多跨平台开发者来说,这一套流程并不友好。 特别是当你的项目主要在 Windows 或 Linux 下开发(例如 Flutter、React Na…...
Python常用模块:time、os、shutil与flask初探
一、Flask初探 & PyCharm终端配置 目的: 快速搭建小型Web服务器以提供数据。 工具: 第三方Web框架 Flask (需 pip install flask 安装)。 安装 Flask: 建议: 使用 PyCharm 内置的 Terminal (模拟命令行) 进行安装,避免频繁切换。 PyCharm Terminal 配置建议: 打开 Py…...