虚幻C++中的细节之类名前面的宏(模块名_API)

这篇具有很好参考价值的文章主要介绍了虚幻C++中的细节之类名前面的宏(模块名_API)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

虚幻引擎是一个强大的游戏开发平台,它为我们提供了非常多的工具和技术,使我们能够构造出具备相当质量的游戏世界。

在利用虚幻引擎进行开发的过程中,有一点非常重要,就是代码的可见性,即代码与代码之间的如何连接,更具体的,我希望集中讨论一下我们每次创建类的时候,类名前面出现的这个宏模块名_API的作用,为什么需要它,它起什么作用,应该怎样使用它。

这就是本篇文章要展示的细节。

一、观察自定义的类

利用引擎的代码创建功能或者编辑器的快捷代码模板创建功能,我们可以很快得创建出一个继承UObject的类

// MyCustomObject.h

#include "CoreMinimal.h"
#include "UObject/Object.h"
#include "MyCustomObject.generated.h"

UCLASS()
class MYGAME_API UMyCustomObject : public UObject
{
    GENERATED_BODY()

public:
    UPROPERTY(EditAnywhere, Category = "Custom Object")
    int32 MyCustomInt;

    UPROPERTY(EditAnywhere, Category = "Custom Object")
    FString MyCustomString;

    UFUNCTION(BlueprintCallable, Category = "Custom Object")
    void MyCustomFunction();
};

// MyCustomObject.cpp

#include "MyCustomObject.h"

void UMyCustomObject::MyCustomFunction()
{
    UE_LOG(LogTemp, Warning, TEXT("MyCustomFunction called!"));
}

这算是非常简单的一个自定义类,其中UMyCustomObject继承自UObject,它添加了一些自定义的属性和函数,这些内容都可以通过蓝图进行编辑或调用。类内的GENERATED_BODY宏用来生成一些用于类管理的模板代码。

这只是一个简单的示例,本篇文章真正要讨论的核心在class关键字和类名UMyCustomObject之间的MYGAME_API,也就是开篇中我们提到的模块名_API

后文中我将统一使用MYGAME_API这一具体例子来指代这个概念。

二、什么是 MYGAME_API

在长期的开发中,我们似乎已经习惯了引擎和IDE帮助我们生成这样模板的代码,以至于始终没有去正视MYGAME_API这个宏的作用。我们更愿意相信它是虚幻代码编写中一个再通常不过的习惯,就算在虚幻的源码中,有时候类名前有它,有时候又没有它,更多人愿意骗自己说它就是一个可有可无的东西。

但是真的是这样的吗?

从单纯c++的角度分析,MYGAME_API就是一个预处理指令,是一个定义为空的宏。如果了解过虚幻的反射系统,或者UHT,就基本明白这个空的宏意味着什么——它用来占位,用来给一些内容打标记,以便在预编译的时候替换进来一些真正起作用的东西。

在虚幻引擎的代码中,MYGAME_API被用来标记一些类以及函数,从而将这些类和函数从模块或者是插件中公布出去,即被MYGAME_API标记的类和函数可以允许被其他模块或者插件访问,也就是我们前文提到的代码的可见性和连接的问题。

三、为什么需要 MYGAME_API

就如前面所说,MYGAME_API的作用就是将原本别的地方访问不到的类和函数公布给他们,从而实现代码的连接。我们用一个例子来直观得感受一下。

创建一个插件,起名为MyGame

没有用MYGAME_API标记的类

#include "CoreMinimal.h"

class MyClass_NonExported
{
public:
    void MyFunction();
};

使用MYGAME_API标记的类

#include "CoreMinimal.h"

class MYGAME_API MyClass_Exported
{
public:
    void MyFunction();
};

另外创建一个插件,起名OtherPluginDependonMyGame,在其模块下试图编写访问MyClass_NonExportedMyClass_Exported的代码:

void UTestObject::MyFunction()
{
	Class_Exported = new MyClass_Exported;
	Class_NonExported = new MyClass_NonExported;

	Class_Exported->MyFunction();
	Class_NonExported->MyFunction();
}

虚幻C++中的细节之类名前面的宏(模块名_API),# 虚幻代码,C++,c++,虚幻,游戏,ue5,游戏引擎

其他的模块可以访问MyClass_Exported的内容,而访问不到MyClass_NonExported的内容。MYGAME_API确实帮助我们控制了代码对外的可见性。

在UBT的源码中,有这样的一段

// Add the import or export declaration for the module
if (Rules.Type == ModuleRules.ModuleType.CPlusPlus)
{
	if(Rules.Target.LinkType == TargetLinkType.Monolithic)
	{
		if (Rules.Target.bShouldCompileAsDLL && (Rules.Target.bHasExports || Rules.ModuleSymbolVisibility == ModuleRules.SymbolVisibility.VisibileForDll))
		{
			Definitions.Add(ModuleApiDefine + "=DLLEXPORT");
		}
		else
		{
			Definitions.Add(ModuleApiDefine + "=");
		}
	}
	else if(Binary == null || SourceBinary != Binary)
	{
		Definitions.Add(ModuleApiDefine + "=DLLIMPORT");
	}
	else if(!Binary.bAllowExports)
	{
		Definitions.Add(ModuleApiDefine + "=");
	}
	else
	{
		Definitions.Add(ModuleApiDefine + "=DLLEXPORT");
	}
}

这里就是一段关于如何实现模块代码可见性的一点小小的内容:根据标记,UBT在编译时为模块添加导入导出的声明,通过这样一种方式在DLL中公布或者不公布模块的某些内容。

通过这样一个小小的特性,我们可以很好的控制外部对自己编写的模块的访问权限。

四、关于 MYGAME_API 的一些小建议

在虚幻引擎代码中使用MYGAME_API宏相对简单。以下是有效使用宏的一些准则:

  • 创建新类或函数时,请确保在声明中包含`MYGAME_API``宏。

  • 如果要创建插件或模块,请确保将MYGAME_API宏包含在需要导出并可用于引擎其他部分的所有类和函数中。

  • 如果使用的是需要MYGAME_API宏的第三方库或插件,请确保将其也包含在代码中。

即使这篇文章读完都没能让你明白MYGAME_API的确切意图是什么,在创建新类或函数时,最好遵循Unreal Engine代码所使用的惯例(即虚幻代码创建工具和IDE工具帮助我们生成的代码模板)。

总结

MYGAME_API宏是虚幻引擎开发的一个重要部分,它允许我们从类和函数的粒度去控制代码的可见性,构建起模块与模块之间的链接。通过有效地使用这个宏,可以确保代码被正确地链接和导出,从而使其对引擎的其他部分可见和可访问。文章来源地址https://www.toymoban.com/news/detail-715871.html

到了这里,关于虚幻C++中的细节之类名前面的宏(模块名_API)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Rust中的宏:声明宏和过程宏

    宏是Rust语言中的一个重要特性,它允许开发人员编写可重用的代码,以便在编译时扩展和生成新的代码。宏可以帮助开发人员减少重复代码,并提高代码的可读性和可维护性。Rust中有两种类型的宏:声明宏和过程宏。 声明宏是一种用于定义新的宏的语法。它使用 macro_rules

    2023年04月22日
    浏览(26)
  • 一分钟了解下JavaScript中的宏任务与微任务

    JavaScript中的宏任务(macro-task)和微任务(micro-task)是指异步任务的两种不同类型。它们的执行顺序是不同的,因此在编写异步代码时需要注意它们之间的区别。 宏任务 宏任务是指由浏览器之外的环境(如操作系统、浏览器事件等)触发的异步任务,例如: setTimeout setInte

    2024年02月13日
    浏览(26)
  • Vue:关于声明式导航中的 跳转、高亮、以及两个类名的定制

    实现导航高亮,实现方式其实,css,JavaScript , Vue ,都可以实现。 其实关于路由导航,我么可以使用vue-router提供的一个全局组件 router-link(来取代a标签)去实现。 router-link的两大特点(能跳转、能高亮) ① router-link 可以跳转,通过配置 to 属性指定路径。其实本质上还是 a 标

    2024年02月10日
    浏览(30)
  • 解决插件在word中的宏禁用问题。MathType, Microsoft Office, powerpoint

    背景:破解版的Microsoft Office,以及破解版的MathType。启动word后,会出现“宏禁用”的警告,并且MathType插件不可用,MathType对象也无法编辑,需要手动点击警告里的“启用”,主要是每次打开MS都得重新启用。 解决方法: 1、在word中依次点击“文件”-“选项”-“加载项”,找

    2024年02月11日
    浏览(56)
  • 2.css公共样式、LOGO SEO优化、常用模块和注册页类名命名、tab栏布局原理、Web服务器

    favicon.ico 一般用于作为缩略的网站标志,它显示在浏览器的地址栏或者标签上。 目前主要的浏览器都支持favicon.ico图标。 favicon图标的制作分为3步: 1.制作favicon图标 2.favicon图标放到网站根目录下 3.HTML页面引入favicon图标 1.制作favicon图标 (1)把品优购图标切成png图片 (2)把png图片

    2024年02月16日
    浏览(37)
  • 【虚幻引擎UE】UE5 三种模式调用API详解(案例基于免费Varest插件)

    想通过UE5 调用API实现GET和POST, 可以通过自己编写C++方法, 或基于相关HTTP请求插件, 如Varest、Http Request、Http Blueprint For Web等等插件进行实现。 本文仅简要介绍实现思路及基于Varest插件的实操案例。 1.如果是无后端直接写代码,可以通过Apifox工具(或其他mock工具)设计接口

    2024年02月07日
    浏览(33)
  • GPTs的创建与使用,自定义GPTs中的Actions示例用法 定义和执行特定任务的功能模块 通过API与外部系统或服务的交互

    Logo:自动生成 Name 介绍 Description 介绍 Instructions 要求或命令等 比如用中文回复,角色。 Knowledge 上传你的知识库,如果你有某一垂直行业的数据,基于数据来回答。比如我有某个芯片的指令集。 Capabilities 都要 Actions:就这个难以理解一点,下面详说含义用法。 Addtional Setting

    2024年02月04日
    浏览(31)
  • Linux网络编程必备的POSIX API的细节

    目录 POSIX API大集合 五元组 三次握手的过程, 内核协议栈分析 listen函数 DDOS攻击, 洪水攻击 DDOS 攻击的应对措施 数据发送  怎么保证顺序?如何保证包地顺序到达(序号 + 确认应答机制 + 重传) TCP断开连接的过程 问题1. 大量的CLOSE_WAIT + FIN_WAIT2是为啥? time_wait状态存在的原因?

    2023年04月27日
    浏览(28)
  • UE 虚幻引擎 C++ 线程锁,作用域锁

    UE 里面的线程锁比较常用的就是 FCriticalSection + FScopeLock。 FCriticalSection 是锁对象。 FScopeLock 是锁的作用域对象。 1. 定义锁对象 定义一个 FCriticalSection 锁对象,这个对象可以是全局的,也可以是类变量,这个根据实际情况使用。唯一需要保证的就是,需要同步的代码都需要

    2024年02月14日
    浏览(23)
  • 虚幻学习笔记16—C++和3DUI(二)

    一、前言         上一篇虚幻学习笔记15—C++和UI(一)中介绍了通过C++代码创建2D的ui,本章主要讲解怎么用C++代码创建3D的UI,在虚幻学习笔记3—UI跟随弹窗这章中讲解了怎样用蓝图创建一个3D的UI,并且和其交互。         本系列使用的虚幻5.2.1,vs2022。 二、实现      

    2024年02月01日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包