当前位置: 首页 > news >正文

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)

本人菜鸟&#xff0c;文中若有代码、术语等错误&#xff0c;欢迎指正 我写的项目地址&#xff1a;https://github.com/liujianjie/GameEngineLightWeight&#xff08;中文的注释适合中国人的你&#xff09; 文章目录前言关键操作代码文件关键代码代码流程代码文件关键代码exter…...

牛客网Python篇数据分析习题(四)

1.现有一个Nowcoder.csv文件&#xff0c;它记录了牛客网的部分用户数据&#xff0c;包含如下字段&#xff08;字段与字段之间以逗号间隔&#xff09;&#xff1a; Nowcoder_ID&#xff1a;用户ID Level&#xff1a;等级 Achievement_value&#xff1a;成就值 Num_of_exercise&a…...

盲盒如何创业?

所谓的“盲盒”&#xff0c;受众群体大部分是那些爱碰运气的人&#xff0c;顾客买的是那种在打开盲盒时一刹那的惊喜感和神秘感&#xff0c;在打开盲盒之前&#xff0c;谁也不知道自己会得到什么&#xff0c;这也是为什么消费者更愿意购买的原因。网上的盲盒&#xff0c;主要是…...

第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 概述 将数据库的读写操作分散到不同的数据库节点上 通常一主多从一台主数据库负责写&#xff0c;多台从数据库负责读。 主库和从库之间会进行数据同步&#xff0c;以保证从库中数据的准确性。 1.2 问题及解决 1.2.1 问题 主从同…...

Allegro如何实现同一个屏幕界面分屏显示操作指导

Allegro如何实现同一个屏幕界面分屏显示操作指导 在做PCB设计的时候,会需要分屏显示,比如一边是放大的视图,另外一边是缩小的视图,Allegro支持同一个屏幕界面下进行分屏显示,如下图 而且会实时同步起来 如何分屏,具体操作如下 点击View...

前后端一些下载与配置(第二篇 第10天过后)nuxt banner redis 短信服务

NUXT 应该是不用怎么装&#xff1f; 有现成的 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 引擎&#xff08;Google Chrome 的内核&#xff09;&#xff0c;利用事件驱动、非阻塞和异步输入输出模型等技术提高性能 可以理解为 Node.js 就是一个服务器端的、非阻塞式I/…...

Bean的生命周期

所谓的生命周期指的是一个对象从诞生到销毁的整个生命过程&#xff0c;我们把这个过程就叫做一个对象的生命周期~~ Bean的生命周期分为以下五大部分&#xff1a; 实例化&#xff08;为 Bean 分配内存空间&#xff09; 设置属性&#xff08;Bean对象注入/装配&#xff09; 初…...

Python学习-----函数2.0(函数对象,名称空间,作用域-->全局变量与局部变量)

目录 前言&#xff1a; 1.函数对象 &#xff08;1&#xff09;函数对象的引用 &#xff08;2&#xff09;函数可以放到序列里面 &#xff08;3&#xff09;函数可以作为参数 &#xff0c; 传递给另一个函数 2.名称空间 3.作用域 &#xff08;1&#xff09;作用域的理解 …...

Java中Json字符串和Java对象的互转

JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式。诞生于 2002 年。易于人阅读和编写。同时也易于机器解析和生成。JSON 是目前主流的前后端数据传输方式。 JSON 采用完全独立于语言的文本格式&#xff0c;但是也使用了类似于 C 语言家族的…...

代码随想录NO42 | 动态规划_Leetcode70. 爬楼梯 (进阶) 322. 零钱兑换 279.完全平方数

动态规划_Leetcode70. 爬楼梯 &#xff08;进阶&#xff09; 322. 零钱兑换 279.完全平方数70. 爬楼梯 &#xff08;进阶&#xff09; 在原题基础上&#xff0c;改为&#xff1a;一步一个台阶&#xff0c;两个台阶&#xff0c;三个台阶&#xff0c;…&#xff0c;直到 m个台阶…...

【C++从入门到放弃】初识C++(基础知识入门详解)

&#x1f9d1;‍&#x1f4bb;作者&#xff1a; 情话0.0 &#x1f4dd;专栏&#xff1a;《C从入门到放弃》 &#x1f466;个人简介&#xff1a;一名双非编程菜鸟&#xff0c;在这里分享自己的编程学习笔记&#xff0c;欢迎大家的指正与点赞&#xff0c;谢谢&#xff01; C基础…...

企业工程项目管理系统源码+spring cloud 系统管理+java 系统设置+二次开发

工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#xff1a;实现对数据字典标签的增删改查操作 2、编码管理&#xff1a;实现对系统编码的增删改查操作 3、用户管理&#xff1a;管理和查看用户角色 4、菜单管理&#xff1a;实现对系统菜单的增删改查操…...

【GPLT 三阶题目集】L3-016 二叉搜索树的结构

二叉搜索树或者是一棵空树&#xff0c;或者是具有下列性质的二叉树&#xff1a; 若它的左子树不空&#xff0c;则左子树上所有结点的值均小于它的根结点的值&#xff1b;若它的右子树不空&#xff0c;则右子树上所有结点的值均大于它的根结点的值&#xff1b;它的左、右子树也分…...

核心交换机安全多业务高性能万兆交换机

RG-S5750-24SFP/12GT交换机是锐捷网络推出的融合了高性能、高安全、多业务的新一代三层交换机。RG-S5750-24SFP/12GT 交换机能够提供灵活的介质接口&#xff0c;满足网络建设中不同介质的连接需要。全千兆的端口形态&#xff0c;加上可扩展的高密度万兆端口&#xff0c;提供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…...

结构体的三种定义方法、结构体类型名(可选标志符)什么时候可以省略

结构体的三种定义方法 一、单独定义&#xff1a; 先定义结构体类型&#xff0c;再定义变量   定义结构体的格式如下&#xff1a;    struct 结构体名 {    若干数据项&#xff1b;    } &#xff1b;   其中&#xff0c;struct为关键字&#xff1b; 结构体名是用户定…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日&#xff0c;国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解&#xff0c;“超级…...

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

Element Plus 表单(el-form)中关于正整数输入的校验规则

目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入&#xff08;联动&#xff09;2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...

技术栈RabbitMq的介绍和使用

目录 1. 什么是消息队列&#xff1f;2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

WPF八大法则:告别模态窗口卡顿

⚙️ 核心问题&#xff1a;阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程&#xff0c;导致后续逻辑无法执行&#xff1a; var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题&#xff1a…...