无法找到模块“mint-ui”的声明文件_UE4 模块,PrivateDependencyModuleNames?_weixin_39785400的博客-程序员宅基地

技术标签: 易语言无模块注入  无法找到模块“mint-ui”的声明文件  模块不存在:public  

d592418a621c3ec7628ca9e80452f017.png

来源:

Ari Arnbjörnsson大佬的推文​twitter.com

文档源:

Ari Arnbjörnsson大佬的PPT​docs.google.com

今天(X)很久很久之前(√)无意间刷到了Ari Arnbjörnsson大佬,关于UE4模块的解析,完美的解答了我心中多年的疑问.还有一些相关的问题,一起记录在这里.(建议先看上面的PPT )

如有理解不当的地方,恳请指正

为什么模块代码文件要区分Public和Private目录?

答:是为了满足模块导出(从模块导出类或者函数供其它模块使用)机制.因为模块里的代码默认是不暴露给其它模块的,所以UE4约定:把需要导出(全导出或部分导出)给其它模块使用的代码文件的头文件放在模块的Public目录下.

  • 模块默认不暴露任何类或函数(如何暴露请看PPT)
  • 不想暴露的头文件可以放进Private文件夹
  • 不会被其它模块引用的模块,可以不区分Public/Private文件夹.(比如游戏(主)模块)
Public目录下只放头文件,因为.cpp文件放这里,其它模块也无法' #include "xxx.cpp" '.

IncludePathModuleNames,DependencyModuleNames的区别?

答:

*注意,问题里没有Public/Private前缀

二者都能使本模块可以包含其它模块Public目录下的头文件,从而调用函数.

但IncludePathModuleNames只能调用定义全部在头文件里的函数.

// Class.h
因为在编译时会将包含的头文件的内容都 拷贝一份到.cpp里,所以定义全部在头文件里的函数能正常工作.
而这带来的问题是:同一个函数,被编译多次(根据它被包含的次数),在大型项目里将 拖慢编译速度.
所以我们为了让函数只编译一次,才会把函数定义放在cpp文件里.

使用DependencyModuleNames时,会进行对两个模块进行链接.故不存在此问题.

只有与其它模块链接之后,才能使用其它模块的定义在.cpp里函数( 若使用了定义在.cpp内函数,但又没将引用到的模块添加到DependencyModuleNames,就会获得"无法解析的外部符号(unresolved external symbol)"错误)
*IncludePathModuleNames是过时的用法,现在一般只用DependencyModuleNames

PublicIncludePathModuleNames, PublicDependencyModuleNames的区别?

PrivateIncludePathModuleNames, PrivateDependencyModuleNames的区别?

PublicDependencyModuleNames, PrivateDependencyModuleNames的区别?

答答答:要回答这个问题,除了要理解"Include与Dependency",就剩明白Public和Private的含义.

其实我也是到现在才完全明白,它俩其实和C++里的访问控制符是类似的,只是多了点小细节

C


*由于IncludePathModuleNames已过时,下面只讨论DependencyModuleNames.

结论:Private隐藏所有信息,Public只传递头文件信息.链接永不传递,需显式在Build.cs里添加.

对于三个模块,无法获得Private中模块的任何信息,可以获得Public中模块的头文件信息.
对于两个模块Public/Private无意义.(可以随意用)

最终结论:建议只使用PrivateDependencyModuleNames.杜绝迷惑.(但应该考虑过多模块静态链接的问题?)

f03b484890b5e3b7fdaa2f0c1ce9fbeb.png
几种我想到的情形图解,对了,大佬的PPT里还有更形象的图片

图片源文件下载

MinimalAPI说明符的作用?

答:暴露该类的类型信息让其它模块可以

  • Cast到该类型
  • 继承该类型
  • 使用内联函数

[YourModuleName]_API宏的作用?

答:

  • 放函数声明前用于暴露该函数
  • 放类声明前用于暴露该类的所有内容

如何正确的包括头文件(使用来自其它模块的类)?

答:首先找到该头文件的完整路径

e3e613988efbdac2beb026cb8b76c21f.png
获取完整路径的方式之一
  • 在.h或cpp中包括头文件#include "Path" : Path是完整路径中Classes或Public的斜杠之后的部分
    • Classes目录是过时的东西,现在都放在Public目录下
  • 在build.cs中添加模块关系 : 模块名是完整路径中Classes或Public之前的部分

模块的类型有多少种可以选择?

答:请查看Projects模块中的EHostType::Type.(UBT里也能找到一样的定义)

  • Engine/Source/Runtime/Projects/Public/ModuleDescriptor.h
  • Engine/Source/Programs/UnrealBuildTool/System/ModuleDescriptor.cs

模块的加载时期的有多少种可以选择?

答:请查看Projects模块中的ELoadingPhase::Type.(UBT里也能找到一样的定义)

  • Engine/Source/Runtime/Projects/Public/ModuleDescriptor.h
  • Engine/Source/Programs/UnrealBuildTool/System/ModuleDescriptor.cs

Precompiled Headers(PCH)文件有什么用?

答:由于编译代码时一般不会单独编译头文件,头文件被包含到每个.cpp里,随着.cpp文件一起编译.因此当多个.cpp包含同一份.h时,就带来了重复编译的问题.

于是PCH出现了,这个文件里的头文件只会被编译一次.

  • PCH包含了所有最常使用的头文件
  • 优先编译
  • 仅在这些最常使用的头文件发生变化时,重新编译一次
    • 包含了PCH的.cpp也会重新编译
    • 最好用在引擎代码或者那种很少变动的代码

Private PCH 和 Shared PCH又是什么?有啥用?

答:它俩是特殊一点的PCH,只需记住几(×)1(√)点,

Private PCH是给本模块用的PCH,Shared PCH是给 依赖本模块的模块用的PCH
一个模块可以使用其他模块定义的Shared PCH
一个模块不能使用自己定义的Shared PCH
模块对PCH的选择只有三个:
-使用本模块定义的Private PCH
-使用引擎自动从 本模块依赖的模块定义的Shared PCH中,选出一个最佳PCH
- 不使用PCH

两者需要在模块的build.cs文件中手动指定

PrivatePCHHeaderFile 
  • 不要手动在模块的.h/.cpp中包含该文件
    • UBT会自动把它注入到每个被编译的.cpp中
  • PCH应该是一种优化层面的东西
    • 不要把它当作一种快捷的"include all"的方式,还是要坚持"IWYU,只包含用到的东西"
    • 你的代码在没有PCH的时候,也能编译通过

对于Shared PCH

  • UE4将自动选择最优的Shared PCH,最终的目的是让选择的Shared PCH尽可能多的涵盖本模块用到的头文件。
Shared PCH的选择范围是本模块依赖的模块中定义的Shared PCH
假如模块A依赖Slate,Core以及CoreUOject模块,且没定义Private PCH,
且只有Slate及Core模块中定义了Shared PCH,
那么,A的Shared PCH就只能从Slate, Core两个模块中选
选哪一个呢?
基于得分来选择——以它俩依赖的<定义了Shared PCH的> 模块数量来作为它们的分数
假设Core模块依赖了TraceLog, Json,假如只有TraceLog模块中定义了Shared PCH,
那么它得1分
假设Slate模块依赖了Core, SourceControl, Json模块,假如Json模块中定义了Shared PCH,
那么它得2分(Core 1 + Json 1)
而且很容易看出,由于Slate的依赖项里包含了Core,那么它Shared PCH很可能包含了大部分Core模块里的头文件,以及其它 额外的头文件,这样,我们就会理所当然的选择使用Slate的Shared PCH,因为我们的模块使用到的头文件,也在Slate的Shared PCH里的概率更大。
因此我们将会选择Slate模块的Shared PCH作为本模块的PCH。
  • 它是一个用于给依赖于本模块的模块使用的PCH
    • 在UE4的一些重要且常用的模块里可以看到它
      • 具体来说:UnrealEd, Engine, Slate, CoreUObject, Core 等.
  • 多个模块使用同一个Shared PCH时,它也只会编译一次

IWYU是什么?有什么作用?

答:IWYU就是Include-What-You-Use,类似于一种代码规范,正确的说法或许是依赖模型(dependency model, 描述文件之间的依赖关系).

在工程中应用IWYU将会带来减少编译时间与重编次数以及利于重构等多种好处.

了解更多有关IWYU:

include-what-you-use的好处​github.com UE4官方文档-IWYU​docs.unrealengine.com
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_39785400/article/details/110812536

智能推荐

Linux常用磁盘管理命令详解_万猫学社的博客-程序员宅基地_linux磁盘管理常用命令

du命令用于查看文件和目录磁盘的使用空间。命令语法:du [参数] [文件或目录名称]参数说明:| 参数 | 说明 ||:--:|:--:|| -a | 列出所有的文件与目录容量。 || -h | 以G、M、K为单位,返回容量。 || -s | 列出总量。 || -S | 列出不包括子目录下的总量。 || -k | 以KBytes为单位,返回容量。 || -m | 以MBytes为单位,返回容量。 |使用示例:列出当前目录下的所有文件夹的容量。

Android中使用AsyncTask异步更新UI界面_IT_xiao小巫的博客-程序员宅基地_android jni后台线程ui

转自:代码来源于使用AsyncTask异步更新UI界面及原理分析|若水工作室 http://blog.92coding.com/index.php/archives/362.html  概述: AsyncTask是在Android SDK 1.5之后推出的一个方便编写后台线程与UI线程交互的辅助类。AsyncTask的内部实现是一个线程池,所有提交的异步任务都会在这个线程池中的工作

opencv java 轮廓提取_Opencv处理图像之轮廓提取_圆圆脸小怪兽的博客-程序员宅基地

本文实例为大家分享了Opencv处理图像之轮廓提取,使用cvfindContours对图像进行轮廓检测,供大家参考,具体内容如下#include#include#includeint main(){IplImage* img = cvLoadImage("E:\\test.bmp",0);IplImage* imgColor = cvCreateImage(cvGetSize(img),8,3);...

视频化表达“吞噬”互联网,文本信息逐渐被替代?_句豆姐姐的博客-程序员宅基地

作者:胡泳转载自:经济观察报未来表达:往下碎和往下“演”  1月19日,2021微信公开课Pro版的微信之夜上,腾讯高级副总裁、微信事业群总裁张小龙表示,视频化表达会成为下一个十年、内容领域的一个主题。  “虽然我们并不清楚,文字还是视频才代表了人类文明的进步,但从个人表达,以及消费程度来说,时代正在往视频化表达方向发展。”张小龙说。  我仔细看了张小龙的“微信公开课”,在朋友圈里写下数点评论:  1、随着视频重要性的提高,文本——长期以来作网络交流的实际手段,其重要性不断走低。文字

故事的力量!!_keminlau的博客-程序员宅基地

http://www.geocities.com/Tokyo/Highrise/6878/story1.htm钉子有一个男孩有著很坏的脾气,於是他的父亲就给了他一袋钉子,并且告诉他,每当发脾气的时候,就钉一根钉子在后院的围篱上。第一天,这个男孩钉下了37根钉子。慢慢地,每天钉下的数量减少了。他发现控制自己的脾气要比钉下那些钉子来得容易些。终於有一天,这个男孩再也不会失去耐性乱发脾气。

ASP.NET MVC+BUI实现表格的操作_diaobiao8107的博客-程序员宅基地

在Web中基于表格的操作,比如添加行、单元格内容编辑等等功能,是完全基于js实现的。但如果程序员完全使用js或者jquery去编写表格控件,则会导致样式不统一,代码量较大等问题,尤其对于不太熟悉js的后端程序员来说,可能会是一个挑战。因此,网络上出现了很多基于表格操作的js控件,帮助程序员尤其是后端程序员也能够编写出漂亮的基于表格的应用。本篇博客以ASP.NET MVC+BUI为例,看如...

随便推点

stm32mp157开发板网卡接口测试_韦东山的博客-程序员宅基地_韦东山mp157固定ip

4.1 有线网卡接口测试此节演示在串口终端下如何设置开发板的 ip 地址,测试网络的连通性。注意:既然是在开发板和电脑之间测试网络,那双方需要有网络连接。两者之间需要有一个路由器,开发板通过网线与路由器连接。而电脑与路由器之间,可以使用网线连接,也可以使用 WIFI 连接。注意:如果要测试全功能版的 2 个网卡,先测一个网卡,然后把它的网线取下来;再接网线到第 2 个网卡并测试。通过 ifconfig 命令查看 ip 地址:通过上图可知,开发板已经自动获得 IP 地址 192.168.1.1

【LVGL 学习】加入内部字体_小石头有大内涵的博客-程序员宅基地_lvglfonttool

使用到的软件LvglFontTool.exe字符转换工具软件界面按照软件界面配置1. 打开lvgl源码中,lv_conf.h 文件,测试例程使用V7.7.0版本在420行加入以下代码#define LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(myFont)// LV_FONT_DECLARE(myFont) “myFont” 是对应软件界面中,请输入的字体名字一栏中的名称在481行加入以下代码#define LV_THEME_DEFAULT

React Native中Navigator的基本使用,实现简单的页面之间的跳转和页面数据传递_迷途的羔羊_的博客-程序员宅基地

效果如下:很简单的例子,大佬勿喷啊...          点击查看多少钱后,自动跳转到超市页面,点击回答价格后,自动跳转回顾客界面,并传递参数回去。 在我使用的0.57.0的版本中,Navigator已被移除,需要安装:npm install react-native-deprecated-custom-components --save然后在使用的地方导入:im...

spring-data-elasticsearch简单案例_xiaolong2230的博客-程序员宅基地_maven spring-data-elasticsearch

关于spring-data-es注解以及案例还可以参照https://blog.csdn.net/qq_43652509/article/details/83989257一、spring-data-elasticsearch 的工程介绍spring-data-elasticsearch 的工程,介绍 Spring Data Elasticsearch 简单的 ES 操作。Spring Data...

DB2 - Instance_mydriverc2的博客-程序员宅基地

IntroductionAn Instance is a logical environment for DB2 Database Manager. Using instance, you can manage databases. Depending on our requirements, you can create multiple instances on one physica

推荐文章

热门文章

相关标签