UE蓝图 返回结果(FunctionResult)节点和源码

news2025/1/10 22:30:44

系列文章目录

UE蓝图 Get节点和源码
UE蓝图 Set节点和源码
UE蓝图 Cast节点和源码
UE蓝图 分支(Branch)节点和源码
UE蓝图 入口(FunctionEntry)节点和源码
UE蓝图 返回结果(FunctionResult)节点和源码


文章目录

  • 系列文章目录
  • 一、FunctionResult节点功能
  • 二、FunctionResult节点用法
  • 三、使用场景
  • 四、实现过程
  • 五、相关源码


一、FunctionResult节点功能

在这里插入图片描述

FunctionResult节点是UE蓝图中用于返回函数执行结果的重要节点之一。它可以帮助您将函数的返回值传递给调用者,并在需要时进行调试和测试。FunctionResult节点通常位于函数的末尾。


二、FunctionResult节点用法

以下是使用FunctionResult节点的一般步骤:

  1. 创建FunctionResult节点:在蓝图中,定义了函数的返回参数后,FunctionResult节点会自动创建显示。
  2. 连接输入引脚:如果函数需要输出参数,你可以将相应的引脚连接到FunctionResult节点的输入引脚上。
  3. 使用返回值:你可以将FunctionResult节点的输出引脚连接到其他节点,以便基于函数的返回值执行进一步的操作。

三、使用场景

UE(Unreal Engine)的蓝图系统中的FunctionResult节点具有多种应用场景,主要涉及到需要获取函数返回值并进行进一步处理的情况。以下是一些常见的应用场景示例:

  1. 条件判断

    • 当你的游戏逻辑需要根据某个函数的返回值来做出决策时,可以使用FunctionResult节点来存储这个返回值,并将其连接到条件判断节点(如Branch节点)上。例如,一个函数可能返回一个布尔值来表示某个条件是否满足,你可以使用FunctionResult节点来捕获这个布尔值,并根据其值来执行不同的逻辑分支。
  2. 变量赋值与状态更新

    • 在游戏运行过程中,你可能需要更新某些变量的值或游戏状态。这些变量或状态可能由某个函数的返回值决定。通过FunctionResult节点,你可以获取函数的返回值,并将其赋给蓝图中的变量或用于更新游戏状态。
  3. 事件响应

    • 在UE中,事件是驱动游戏逻辑的重要机制。当某个事件发生时(如用户点击按钮、碰撞检测等),你可能会调用一个函数来处理这个事件,并根据函数的返回值来执行后续操作。FunctionResult节点可以帮助你捕获这些返回值,并据此作出响应。
  4. 数据传递与处理

    • 在复杂的游戏逻辑中,数据可能需要在不同的节点和函数之间传递。FunctionResult节点可以作为数据传递的桥梁,将一个函数的返回值传递给另一个函数或节点进行进一步处理。这种传递可以是数值、对象引用、字符串等各种数据类型。
  5. 异步操作

    • 在UE中,有些函数可能是异步执行的,即它们不会立即返回结果,而是在一段时间后通过回调或事件来通知结果。在这种情况下,你可以使用FunctionResult节点来等待异步操作完成并获取其结果。这通常涉及到使用延迟节点(Delay)和事件调度(Event Dispatch)来管理异步逻辑。

需要注意的是,虽然FunctionResult节点在蓝图系统中非常有用,但它只适用于能够返回值的函数。对于没有返回值的函数(返回类型为void),FunctionResult节点将不会有任何作用。此外,如果函数有多个返回值,你可能需要使用多个FunctionResult节点或者使用结构体(Struct)来封装多个返回值。

总之,FunctionResult节点在UE蓝图系统中广泛应用于条件判断、变量赋值、事件响应、数据传递和异步操作等场景,帮助开发者更加灵活地管理和处理函数的返回值。

四、实现过程

  • 创建输入引脚
  • 调用FKCHandler_FunctionEntry.RegisterNet注册返回值引脚
virtual void RegisterNet(FKismetFunctionContext& Context, UEdGraphPin* Net) override
{
	// Do not register as a default any Pin that comes from being Split
	if (Net->ParentPin == nullptr)
	{
		FString NetPinName = Net->PinName.ToString();
		for (FBPTerminal& ResultTerm : Context.Results)
		{
			if ((ResultTerm.Name == NetPinName) && (ResultTerm.Type == Net->PinType))
			{
				Context.NetMap.Add(Net, &ResultTerm);
				return;
			}
		}
		FBPTerminal* Term = new FBPTerminal();
		Context.Results.Add(Term);
		Term->CopyFromPin(Net, MoveTemp(NetPinName));
		Context.NetMap.Add(Net, Term);
	}
}
  • 调用Compile编译创建Statement
	virtual void Compile(FKismetFunctionContext& Context, UEdGraphNode* Node) override
	{
		static const FBoolConfigValueHelper ExecutionAfterReturn(TEXT("Kismet"), TEXT("bExecutionAfterReturn"), GEngineIni);

		if (ExecutionAfterReturn)
		{
			// for backward compatibility only
			FKCHandler_VariableSet::Compile(Context, Node);
		}
		else
		{
			GenerateAssigments(Context, Node);

			if (Context.IsDebuggingOrInstrumentationRequired() && Node)
			{
				FBlueprintCompiledStatement& TraceStatement = Context.AppendStatementForNode(Node);
				TraceStatement.Type = Context.GetWireTraceType();
				TraceStatement.Comment = Node->NodeComment.IsEmpty() ? Node->GetName() : Node->NodeComment;
			}

			// always go to return
			FBlueprintCompiledStatement& GotoStatement = Context.AppendStatementForNode(Node);
			GotoStatement.Type = KCST_GotoReturn;
		}
	}

五、相关源码

源码文件:
K2Node_FunctionResult.h
K2Node_FunctionResult.cpp
相关类:
FKCHandler_FunctionResult
K2Node_FunctionResult
在这里插入图片描述


class FKCHandler_FunctionResult : public FKCHandler_VariableSet
{
public:
	FKCHandler_FunctionResult(FKismetCompilerContext& InCompilerContext)
		: FKCHandler_VariableSet(InCompilerContext)
	{
	}

	virtual void RegisterNet(FKismetFunctionContext& Context, UEdGraphPin* Net) override
	{
		// Do not register as a default any Pin that comes from being Split
		if (Net->ParentPin == nullptr)
		{
			FString NetPinName = Net->PinName.ToString();
			for (FBPTerminal& ResultTerm : Context.Results)
			{
				if ((ResultTerm.Name == NetPinName) && (ResultTerm.Type == Net->PinType))
				{
					Context.NetMap.Add(Net, &ResultTerm);
					return;
				}
			}
			FBPTerminal* Term = new FBPTerminal();
			Context.Results.Add(Term);
			Term->CopyFromPin(Net, MoveTemp(NetPinName));
			Context.NetMap.Add(Net, Term);
		}
	}

	virtual void Compile(FKismetFunctionContext& Context, UEdGraphNode* Node) override
	{
		static const FBoolConfigValueHelper ExecutionAfterReturn(TEXT("Kismet"), TEXT("bExecutionAfterReturn"), GEngineIni);

		if (ExecutionAfterReturn)
		{
			// for backward compatibility only
			FKCHandler_VariableSet::Compile(Context, Node);
		}
		else
		{
			GenerateAssigments(Context, Node);

			if (Context.IsDebuggingOrInstrumentationRequired() && Node)
			{
				FBlueprintCompiledStatement& TraceStatement = Context.AppendStatementForNode(Node);
				TraceStatement.Type = Context.GetWireTraceType();
				TraceStatement.Comment = Node->NodeComment.IsEmpty() ? Node->GetName() : Node->NodeComment;
			}

			// always go to return
			FBlueprintCompiledStatement& GotoStatement = Context.AppendStatementForNode(Node);
			GotoStatement.Type = KCST_GotoReturn;
		}
	}

	virtual bool RequiresRegisterNetsBeforeScheduling() const override
	{
		return true;
	}
};

#if WITH_EDITORONLY_DATA
namespace
{
	void GatherFunctionResultNodeForLocalization(const UObject* const Object, FPropertyLocalizationDataGatherer& PropertyLocalizationDataGatherer, const EPropertyLocalizationGathererTextFlags GatherTextFlags)
	{
		const UK2Node_FunctionResult* const FunctionResultNode = CastChecked<UK2Node_FunctionResult>(Object);

		// Function Result (aka, Return) nodes always report their values as being the default
		// but we still need to gather them as they are the only place the values are defined
		const FString PathToObject = FunctionResultNode->GetPathName();
		for (const UEdGraphPin* Pin : FunctionResultNode->Pins)
		{
			if (!Pin->DefaultTextValue.IsEmpty())
			{
				PropertyLocalizationDataGatherer.GatherTextInstance(Pin->DefaultTextValue, FString::Printf(TEXT("%s.%s"), *PathToObject, *Pin->GetName()), /*bIsEditorOnly*/true);
			}
		}

		PropertyLocalizationDataGatherer.GatherLocalizationDataFromObject(FunctionResultNode, GatherTextFlags);
	}
}
#endif

UK2Node_FunctionResult::UK2Node_FunctionResult(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
#if WITH_EDITORONLY_DATA
	{ static const FAutoRegisterLocalizationDataGatheringCallback AutomaticRegistrationOfLocalizationGatherer(UK2Node_FunctionResult::StaticClass(), &GatherFunctionResultNodeForLocalization); }
#endif
}

FText UK2Node_FunctionResult::GetNodeTitle(ENodeTitleType::Type TitleType) const
{
	if (ENodeTitleType::MenuTitle == TitleType)
	{
		return NSLOCTEXT("K2Node", "ReturnNodeMenuTitle", "Add Return Node...");
	}
	return NSLOCTEXT("K2Node", "ReturnNode", "Return Node");
}

void UK2Node_FunctionResult::AllocateDefaultPins()
{
	CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute);

	if (UFunction* const Function = FunctionReference.ResolveMember<UFunction>(GetBlueprintClassFromNode()))
	{
		CreatePinsForFunctionEntryExit(Function, /*bIsFunctionEntry=*/ false);
	}

	Super::AllocateDefaultPins();

	FFillDefaultPinValueHelper::FillAll(this);
}

bool UK2Node_FunctionResult::CanCreateUserDefinedPin(const FEdGraphPinType& InPinType, EEdGraphPinDirection InDesiredDirection, FText& OutErrorMessage)
{
	bool bResult = Super::CanCreateUserDefinedPin(InPinType, InDesiredDirection, OutErrorMessage);
	if (bResult)
	{
		if(InDesiredDirection == EGPD_Output)
		{
			OutErrorMessage = NSLOCTEXT("K2Node", "AddOutputPinError", "Cannot add output pins to function result node!");
			bResult = false;
		}
	}
	return bResult;
}

UEdGraphPin* UK2Node_FunctionResult::CreatePinFromUserDefinition(const TSharedPtr<FUserPinInfo> NewPinInfo)
{
	UEdGraphPin* Pin = CreatePin(EGPD_Input, NewPinInfo->PinType, NewPinInfo->PinName);
	CastChecked<UEdGraphSchema_K2>(GetSchema())->SetPinAutogeneratedDefaultValue(Pin, NewPinInfo->PinDefaultValue);
	return Pin;
}

void UK2Node_FunctionResult::FixupPinStringDataReferences(FArchive* SavingArchive)
{
	Super::FixupPinStringDataReferences(SavingArchive);
	if (SavingArchive)
	{
		UpdateUserDefinedPinDefaultValues();
	}
}

FNodeHandlingFunctor* UK2Node_FunctionResult::CreateNodeHandler(FKismetCompilerContext& CompilerContext) const
{
	return new FKCHandler_FunctionResult(CompilerContext);
}

FText UK2Node_FunctionResult::GetTooltipText() const
{
	return NSLOCTEXT("K2Node", "ReturnNodeTooltip", "The node terminates the function's execution. It returns output parameters.");
}

void UK2Node_FunctionResult::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const
{
	// actions get registered under specific object-keys; the idea is that 
	// actions might have to be updated (or deleted) if their object-key is  
	// mutated (or removed)... here we use the node's class (so if the node 
	// type disappears, then the action should go with it)
	UClass* ActionKey = GetClass();
	// to keep from needlessly instantiating a UBlueprintNodeSpawner, first   
	// check to make sure that the registrar is looking for actions of this type
	// (could be regenerating actions for a specific asset, and therefore the 
	// registrar would only accept actions corresponding to that asset)
	if (ActionRegistrar.IsOpenForRegistration(ActionKey))
	{
		UBlueprintNodeSpawner* NodeSpawner = UBlueprintNodeSpawner::Create(GetClass());
		check(NodeSpawner != nullptr);

		ActionRegistrar.AddBlueprintAction(ActionKey, NodeSpawner);
	}
}

bool UK2Node_FunctionResult::IsCompatibleWithGraph(UEdGraph const* Graph) const
{
	auto K2Schema = Cast<const UEdGraphSchema_K2>(Graph ? Graph->GetSchema() : nullptr);
	const bool bIsConstructionScript = (K2Schema != nullptr) ? K2Schema->IsConstructionScript(Graph) : false;
	const bool bIsCompatible = (K2Schema != nullptr) ? (EGraphType::GT_Function == K2Schema->GetGraphType(Graph)) : false;
	return bIsCompatible && !bIsConstructionScript && Super::IsCompatibleWithGraph(Graph);
}

TArray<UK2Node_FunctionResult*> UK2Node_FunctionResult::GetAllResultNodes() const
{
	TArray<UK2Node_FunctionResult*> AllResultNodes;
	if (auto Graph = GetGraph())
	{
		Graph->GetNodesOfClass(AllResultNodes);
	}
	return AllResultNodes;
}

void UK2Node_FunctionResult::PostPlacedNewNode()
{
	Super::PostPlacedNewNode();

	// adhere to the function's inherited signature (if there is one)
	SyncWithEntryNode();
	// reflect any user added outputs (tracked by pre-existing result nodes)
	SyncWithPrimaryResultNode();
}

void UK2Node_FunctionResult::PostPasteNode()
{
	Super::PostPasteNode();

	// adhere to the function's inherited signature (if there is one)
	SyncWithEntryNode();
	// reflect any user added outputs (tracked by pre-existing result nodes)
	SyncWithPrimaryResultNode();
	// reflect editability of node in pins
	MakePinsEditable();
}

bool UK2Node_FunctionResult::CanUserDeleteNode() const
{
	bool bCanDelete = true;
	if (!bIsEditable)
	{
		if (UEdGraph* Graph = GetGraph())
		{
			bCanDelete = false;
			for (UEdGraphNode* Node : Graph->Nodes)
			{
				UK2Node_FunctionResult* ResultNode = Cast<UK2Node_FunctionResult>(Node);
				if (ResultNode && ResultNode != this)
				{
					bCanDelete = true;
					break;
				}
			}
		}
	}
	return bCanDelete;
}

void UK2Node_FunctionResult::SyncWithEntryNode()
{
	bool bWasSignatureMismatched = false;
	if (UEdGraph* Graph = GetGraph())
	{
		for (UEdGraphNode* Node : Graph->Nodes)
		{
			if (UK2Node_FunctionEntry* EntryNode = Cast<UK2Node_FunctionEntry>(Node))
			{
				bWasSignatureMismatched = !EntryNode->FunctionReference.IsSameReference(FunctionReference) || (!EntryNode->bIsEditable && UserDefinedPins.Num() > 0);

				// If the entry is editable, so is the result
				bIsEditable = EntryNode->bIsEditable;
				FunctionReference = EntryNode->FunctionReference;
				break;
			}
		}
	}

	if (bWasSignatureMismatched)
	{
		// to handle pasting of a result node from one function into another;
		// if the new function is not editable (like for one that is overidden), 
		// then we shouldn't have userdefined pins
		if (!bIsEditable)
		{
			// iterate backwards so we can remove items from the list as we go
			for (int32 UserPinIndex = UserDefinedPins.Num() - 1; UserPinIndex >= 0; --UserPinIndex)
			{
				RemoveUserDefinedPin(UserDefinedPins[UserPinIndex]);
			}
		}
		
		ReconstructNode();
	}
}

void UK2Node_FunctionResult::SyncWithPrimaryResultNode()
{
	UK2Node_FunctionResult* PrimaryNode = nullptr;
	TArray<UK2Node_FunctionResult*> AllResultNodes = GetAllResultNodes();
	for (auto ResultNode : AllResultNodes)
	{
		if (ResultNode && (this != ResultNode))
		{
			PrimaryNode = ResultNode;
			break;
		}
	}

	if (PrimaryNode)
	{
		FunctionReference = PrimaryNode->FunctionReference;
		bIsEditable = PrimaryNode->bIsEditable;

		// Temporary array that will contain our list of Old Pins that are no longer part of the return signature
		TArray< TSharedPtr<FUserPinInfo> > OldPins = UserDefinedPins;

		// Temporary array that will contain our list of Signature Pins that need to be added
		TArray< TSharedPtr<FUserPinInfo> > SignaturePins = PrimaryNode->UserDefinedPins;

		for (int OldIndex = OldPins.Num() - 1; OldIndex >= 0; --OldIndex)
		{
			TSharedPtr<FUserPinInfo> OldPin = OldPins[OldIndex];

			if (!OldPin.IsValid())
			{
				OldPins.RemoveAt(OldIndex);
			}
			else
			{
				for (int SignatureIndex = SignaturePins.Num() - 1; SignatureIndex >= 0; --SignatureIndex)
				{
					TSharedPtr<FUserPinInfo> SignaturePin = SignaturePins[SignatureIndex];
					if (!SignaturePin.IsValid())
					{
						SignaturePins.RemoveAt(SignatureIndex);
					}
					else if (OldPin->PinName == SignaturePin->PinName &&
						OldPin->PinType == SignaturePin->PinType &&
						OldPin->DesiredPinDirection == SignaturePin->DesiredPinDirection)
					{
						// We have a match between our Signature pins and our Old Pins,
						// so we can leave the old pin as is by removing it from both temporary lists.
						OldPins.RemoveAt(OldIndex);
						SignaturePins.RemoveAt(SignatureIndex);
						break;
					}
				}
			}
		}

		// Remove old pins that are not part of the primary node signature
		for (TSharedPtr<FUserPinInfo> OldPinToRemove : OldPins)
		{
			RemoveUserDefinedPin(OldPinToRemove);
		}

		// Add pins that don't exist yet but are part of the primary node signature
		for (TSharedPtr<FUserPinInfo> SignaturePinToAdd : SignaturePins)
		{
			TSharedPtr<FUserPinInfo> NewPinInfo = MakeShareable(new FUserPinInfo());
			NewPinInfo->PinName = SignaturePinToAdd->PinName;
			NewPinInfo->PinType = SignaturePinToAdd->PinType;
			NewPinInfo->DesiredPinDirection = SignaturePinToAdd->DesiredPinDirection;
			UserDefinedPins.Add(NewPinInfo);
		}

		ReconstructNode();
	}
}

void UK2Node_FunctionResult::MakePinsEditable()
{
	// only do this step if this node is editable
	if (IsEditable())
	{
		// for each pin, excluding the 'exec' pin
		for (int PinIdx = 1; PinIdx < Pins.Num(); ++PinIdx)
		{
			UEdGraphPin* Pin = Pins[PinIdx];
			if (!UserDefinedPinExists(Pin->GetFName()))
			{
				UserDefinedPins.Add(MakeShared<FUserPinInfo>(*Pin));
			}
		}
	}
}

void UK2Node_FunctionResult::ValidateNodeDuringCompilation(class FCompilerResultsLog& MessageLog) const
{
	Super::ValidateNodeDuringCompilation(MessageLog);

	auto AllResultNodes = GetAllResultNodes();
	UK2Node_FunctionResult* OtherResult = AllResultNodes.Num() ? AllResultNodes[0] : nullptr;
	if (OtherResult && (OtherResult != this))
	{
		for (auto Pin : Pins)
		{
			auto OtherPin = OtherResult->FindPin(Pin->PinName);
			if (!OtherPin || (OtherPin->PinType != Pin->PinType))
			{
				MessageLog.Error(*NSLOCTEXT("K2Node", "FunctionResult_DifferentReturnError", "Return nodes don't match each other: @@, @@").ToString(), this, OtherResult);
				break;
			}
		}
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1462566.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Leetcode 993】二叉树的堂兄弟节点 —— 回溯法

993. 二叉树的堂兄弟节点 在二叉树中&#xff0c;根节点位于深度0处&#xff0c;每个深度为k的节点的子节点位于深度k1处。 如果二叉树的两个节点深度相同&#xff0c;但 父节点不同 &#xff0c;则它们是一对堂兄弟节点。 我们给出了具有唯一值的二叉树的根节点root&#x…

week04day02(爬虫02)

<span>: 通常用于对文本的一部分进行样式设置或脚本操作。<a>: 定义超链接&#xff0c;用于创建链接到其他页面或资源的文本。<img>: 用于插入图像。<br>: 用于插入换行。 姓名&#xff1a;<input type"text" value"lisi">…

ChatGPT丨“成像光谱遥感技术中的AI革命:ChatGPT应用指南“

遥感技术主要通过卫星和飞机从远处观察和测量我们的环境&#xff0c;是理解和监测地球物理、化学和生物系统的基石。ChatGPT是由OpenAI开发的最先进的语言模型&#xff0c;在理解和生成人类语言方面表现出了非凡的能力。本文重点介绍ChatGPT在遥感中的应用&#xff0c;人工智能…

【踩坑专栏】主机ping虚拟机失败

我出现的问题finalshell连接超时&#xff0c;ping了一下发现ping都ping不通&#xff0c;于是发现问题所在。 最开始我是把虚拟机的网络设置改为桥接模式&#xff0c;问题解决了&#xff0c;但是这种模式的问题就是每次开机&#xff0c;ip都会改变&#xff0c;因此非常麻烦&…

Prometheus+TDengine集群实现监控体系高可用

背景 为避免再次出现因Prometheus宕机导致业务无法查看历史数据受到影响&#xff0c;准备将Prometheus架构从单节点方式升级为高可用集群方式并将后端存储由本地存储改为远端分布式时序数据库存储。分布式时序数据库采用国产数据库TDengine。 架构 解释&#xff1a;虚线代表P…

LiveGBS流媒体平台GB/T28181功能-自定义收流端口区间30000至30249UDP端口TCP端区间配置及相关端口复用问题说明

LiveGBS自定义收流端口区间30000至30249UDP端口TCP端区间配置及相关端口复用问题说明 1、收流端口配置1.1、INI配置1.2、页面配置 2、相关问题3、最少可以开放多少端口3.1、端口复用3.2、配置最少端口如下 4、搭建GB28181视频直播平台 1、收流端口配置 1.1、INI配置 可在lives…

Word大珩助手是一款功能丰富的Office Word插件

Word大珩助手是一款功能丰富的Office Word插件&#xff0c;旨在提高用户在处理文档时的效率。它具有多种实用的功能&#xff0c;能够帮助用户轻松修改、优化和管理Word文件&#xff0c;从而打造出专业而精美的文档。 下载地址 网盘下载&#xff1a;PPT大珩助手 密码:acaq 功…

新版Java面试专题视频教程——多线程篇②

新版Java面试专题视频教程——多线程篇② 0. 问题汇总0.1 线程的基础知识0.2 线程中并发安全0.3 线程池0.4 使用场景 1.线程的基础知识2.线程中并发锁3.线程池3.1 说一下线程池的核心参数&#xff08;线程池的执行原理知道嘛&#xff09;3.2 线程池中有哪些常见的阻塞队列Array…

工厂方法模式Factory Method

1.模式定义 定义一个用于创建对象的接口&#xff0c;让子类决定实例化哪一个类。Factory Method 使得一个类的实例化延迟到子类 2.使用场景 1.当你不知道改使用对象的确切类型的时候 2.当你希望为库或框架提供扩展其内部组件的方法时 主要优点&#xff1a; 1.将具体产品和创建…

记录一次数据资源共享平台数据更新后不能展示的问题

一、数据资源共享平台问题 数据资源共享平台数据更新后,在前台展示页面不能展示和查询;以社会关注重大案件为例。 1、更新 输入配置: 输出配置: 更新配置: 手动点击运行。 2、Kingbase数据库查询 数据库原有数据52条,更新后数据有177条;

django rest framework 学习笔记-实战商城

01项目环境搭建_哔哩哔哩_bilibili 本博客借鉴至大佬的视频学习笔记 # 创建项目 django-admin startproject MyShop# 创建app E:\desktop\my_drf\MyShop>django-admin startapp goodsE:\desktop\my_drf\MyShop>django-admin startapp orderE:\desktop\my_drf\MyShop>…

C++从入门到精通 第十七章(终极案例)

写在前面&#xff1a; 本系列专栏主要介绍C的相关知识&#xff0c;思路以下面的参考链接教程为主&#xff0c;大部分笔记也出自该教程&#xff0c;笔者的原创部分主要在示例代码的注释部分。除了参考下面的链接教程以外&#xff0c;笔者还参考了其它的一些C教材&#xff08;比…

互联网高科技公司领导AI工业化,MatrixGo加速人工智能落地

作者&#xff1a;吴宁川 AI&#xff08;人工智能&#xff09;工业化与AI工程化正在引领人工智能的大趋势。AI工程化主要从企业CIO角度&#xff0c;着眼于在企业生产环境中规模化落地AI应用的工程化举措&#xff1b;而AI工业化则从AI供应商的角度&#xff0c;着眼于以规模化方式…

Linux 权限详解

目录 一、权限的概念 二、权限管理 三、文件访问权限的相关设置方法 3.1chmod 3.2chmod ax /home/abc.txt 一、权限的概念 Linux 下有两种用户&#xff1a;超级用户&#xff08; root &#xff09;、普通用户。 超级用户&#xff1a;可以再linux系统下做任何事情&#xff…

程序媛的mac修炼手册-- 如何彻底卸载Python

啊&#xff0c;前段时间因为想尝试chatgpt的API&#xff0c;需要先创建一个python虚拟环境来安装OpenAI Python library. 结果&#xff0c;不出意外的出意外了&#xff0c;安装好OpenAI Python library后&#xff0c;因为身份认证问题&#xff0c;根本就没有获取API key的权限…

Apache Doris:从诞生到云原生时代的演进、技术亮点与未来展望

目录 前言 Apache Doris介绍 作者介绍 Apache Doris特性 Doris 数据流程 极简结构 高效自运维 高并发场景支持 MPP 执行引擎 明细与聚合模型的统一 便捷数据接入 Apache Doris 极速 1.0 时代 极速 列式内存布局 向量化的计算框架 Cache 亲和度 虚函数调用 SI…

Servlet(1)

文章目录 什么是ServletServlet 主要做的工作 第一个Servlet程序1.创建项目2. 引入依赖3. 创建目录1) 创建 webapp 目录2) 创建 web.xml3) 编写 web.xml 4. 编写代码5. 打包程序7. 验证程序 什么是Servlet Servlet 是一种实现动态页面的技术. 是一组 Tomcat 提供给程序猿的 AP…

Nginx配置组成与性能调优

目录 一、Nginx配置介绍 1. 模块组成 2. 图示 3. 相关框架 二. 配置调优 1. 全局配置 1.1 关闭版本和修改版本 1.2 修改启动的进程数 1.3 cpu与work进程绑定 1.4 pid路径 1.5 nginx进程的优先级&#xff08;work进程的优先级&#xff09; 1.6 调试work进程打开的文…

C++:static关键字

一、static成员变量(类变量、静态成员变量) 1、不属于类&#xff1b; 2、必须初始化&#xff1b; 3、同类中所有对象共享&#xff1b; 访问&#xff1a;类::类变量 &#xff0c; 对象.类变量 &#xff0c; 对象指针->类变量&#xff1b;底层都是类::类变量 …

3DSC特征描述符、对应关系可视化以及ICP配准

一、3DSC特征描述符可视化 C #include <pcl/point_types.h> #include <pcl/point_cloud.h> #include <pcl/search/kdtree.h> #include <pcl/io/pcd_io.h> #include <pcl/features/normal_3d_omp.h>//使用OMP需要添加的头文件 #include <pcl…