UE5以插件的形式加载第三方库

news2025/3/15 23:14:28

之前在UE中加载第三方库的形式是以静态或者动态链接的形式加载但是不太容易复用。就想着能不能以插件的形式加载第三方库,这样直接把插件打包发行就可以复用了,之前也找过相应的教程但是很难找到比较简单易懂的教程,要么是比较复杂,要么是自己跟着教程做了一遍但是打包插件的时候,打包不成功。自己在经过各种查找教程及自己总结,发现了一种感觉相对比较简单的方法,下面把整体的过程介绍一下。
1 先创建一个C++的UE 项目,在项目中创建一个空白的插件,可以使用不同的UE版本,博主使用的是UE5.5 如下图
在这里插入图片描述
在这里插入图片描述
在MyPlugin下新建 ThirdParty文件夹,在ThirdParty文件下新建
include,lib,Win64文件夹,在include文件夹下放需要调用的第三放库的.h文件,在lib文件下放相应的.lib文件,Win64下放相应的.dll 文件。我这里用的 pch.h Wll_Dll.lib Wll_Dll.dll (创建第三库的方法之前写过,这里不再赘述)
在这里插入图片描述
2 下面开始设置MyPlugin.Build.cs的设置,整体的代码如下

// Copyright Epic Games, Inc. All Rights Reserved.

using System.IO;
using UnrealBuildTool;

public class MyPlugin : ModuleRules
{
	public MyPlugin(ReadOnlyTargetRules Target) : base(Target)
	{
        // 使用共享 PCH,减少编译时间
        PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;

        // 添加依赖模块,确保 UHT 正确生成代码
        PublicDependencyModuleNames.AddRange(new string[] {
            "Core",
            "CoreUObject",
            "Engine"
        });

        PrivateDependencyModuleNames.AddRange(new string[] {
            "Slate",
            "SlateCore"
        });

        // 获取插件目录路径
        string PluginPath = ModuleDirectory;
        string ThirdPartyPath = Path.Combine(PluginPath, "../../ThirdParty");


        // 确保 DLL 在打包时会被复制到 Binaries/Win64
        if (Target.Platform == UnrealTargetPlatform.Win64)
        {
            string DLLPath = Path.Combine(ThirdPartyPath, "Win64", "Wll_Dll.dll");

            // 添加运行时依赖,确保 DLL 被复制到 Binaries 目录
            RuntimeDependencies.Add("$(PluginDir)/Binaries/Win64/Wll_Dll.dll", DLLPath, StagedFileType.NonUFS);
        }
    }
}

在运行时加载.DLL 关闭时卸载,MyPlugin.h的代码如下

#pragma once

#include "Modules/ModuleManager.h"
// DLL 句柄和函数指针
void* DLLHandle = nullptr;
typedef int (*AddNumbersFunc)(int, int);
AddNumbersFunc AddNumbersPtr = nullptr;
class FMyPluginModule : public IModuleInterface
{
public:

	/** IModuleInterface implementation */
	virtual void StartupModule() override;
	virtual void ShutdownModule() override;
};

MyPlugin.cpp 的代码如下

// Copyright Epic Games, Inc. All Rights Reserved.

#include "MyPlugin.h"
#include "Misc/Paths.h"
#include "HAL/PlatformProcess.h"
#define LOCTEXT_NAMESPACE "FMyPluginModule"

void FMyPluginModule::StartupModule()
{
    // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
    FString DLLPath = FPaths::Combine(FPaths::ProjectPluginsDir(), TEXT("MyPlugin/Binaries/Win64/Wll_Dll.dll"));
    UE_LOG(LogTemp, Warning, TEXT("Trying to load DLL from path: %s"), *DLLPath);

    if (!FPaths::FileExists(DLLPath))
    {
        UE_LOG(LogTemp, Error, TEXT("DLL not found at: %s"), *DLLPath);
        return;
    }

    // 加载 DLL
    DLLHandle = FPlatformProcess::GetDllHandle(*DLLPath);
    if (!DLLHandle)
    {

        UE_LOG(LogTemp, Error, TEXT("Failed to load DLL: %s"), *DLLPath);
        return;
    }

    // 绑定 DLL 函数
    AddNumbersPtr = (AddNumbersFunc)FPlatformProcess::GetDllExport(DLLHandle, TEXT("Add"));//Dll 的两个导出函数 名 分别是 Add,Log
    if (!AddNumbersPtr)
    {
        UE_LOG(LogTemp, Error, TEXT("Failed to bind AddNumbers function from DLL"));
    }
    else
    {
        UE_LOG(LogTemp, Warning, TEXT("AddNumbers function bound successfully"));
    }
}

void FMyPluginModule::ShutdownModule()
{
	// This function may be called during shutdown to clean up your module.  For modules that support dynamic reloading,
	// we call this function before unloading the module.
    if (DLLHandle)
    {
        FPlatformProcess::FreeDllHandle(DLLHandle);
        DLLHandle = nullptr;
        UE_LOG(LogTemp, Warning, TEXT("DLL Unloaded Successfully."));
    }
}

#undef LOCTEXT_NAMESPACE
	
IMPLEMENT_MODULE(FMyPluginModule, MyPlugin)

创建c++的蓝图函数库如下,在蓝图库函数中创建调用函数并暴露给蓝图使用
在这里插入图片描述
MyBlueprintFunctionLibrary.h 的代码如下

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "MyBlueprintFunctionLibrary.generated.h"

/**
 * 
 */
UCLASS()
class MYPLUGIN_API UMyBlueprintFunctionLibrary : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()
public:
    UFUNCTION(BlueprintCallable, Category = "MyPlugin")
    static int CallAddNumbers(int A, int B);
};

MyBlueprintFunctionLibrary.cpp的代码如下

 if (AddNumbersPtr)
 {
     return AddNumbersPtr(A, B); // 调用 DLL 中的函数
 }
 else
 {
     UE_LOG(LogTemp, Error, TEXT("AddNumbersPtr is NULL!"));
     return -1; // 如果函数指针为空,返回错误
 }

以上就是整体的创建流程及完整的运行代码,下面贴上运行结果
在这里插入图片描述
在这里插入图片描述
现在打包还是不能够成功的,得在MyPlugin.uplugin 加上白名单
代码 “WhitelistPlatforms”: [“Win64”] 完整的MyPlugin.uplugin 代码如下

{
	"FileVersion": 3,
	"Version": 1,
	"VersionName": "1.0",
	"FriendlyName": "MyPlugin",
	"Description": "",
	"Category": "Other",
	"CreatedBy": "",
	"CreatedByURL": "",
	"DocsURL": "",
	"MarketplaceURL": "",
	"SupportURL": "",
	"CanContainContent": true,
	"IsBetaVersion": false,
	"IsExperimentalVersion": false,
	"Installed": false,
	"Modules": [
		{
			"Name": "MyPlugin",
			"Type": "Runtime",
			"LoadingPhase": "Default",
			"WhitelistPlatforms": [
				"Win64"
			]
		}
	]
}

加上后就可以打包插件了,也可以给别人使用你这个插件,好了本片文章到此结束,还要把ThirdParty 文件夹复制到打包好的插件中。

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

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

相关文章

Vue3全局化配置(ConfigProvider)

效果如下图: 在线预览 APIs ConfigProvider 参数说明类型默认值theme主题对象Theme{}abstractboolean是否不存在 DOM 包裹元素truetagstringConfigProvider 被渲染成的元素,abstract 为 true 时有效‘div’ Theme Type 名称说明类型默认值common?全…

Centos7系统基于docker下载ollama部署Deepseek-r1(GPU版不踩坑)

目录 一、Docker下载安装 二、Ollama安装 三、部署Deepseek-R1 一、Docker下载安装 1、更新源 sudo yum update -y 2、下载依赖包 yum install -y yum-utils device-mapper-persistent-data lvm2 3、添加docker远程仓库地址 yum-config-manager --add-repo http://down…

【工具】C#游戏防沉迷小工具

背景介绍 嘿,各位小伙伴!今天想跟大家唠唠我为啥要搞这么个防沉迷小工具。 咱都清楚,现在这游戏啊,玩起来那叫一个带劲,但时间一长,不仅眼睛累,心也跟着累。有些游戏,规则定得挺有意…

深圳南柯电子|净水器EMC测试整改:水质安全与电磁兼容性的双赢

在当今注重健康生活的时代,净水器作为家庭用水安全的第一道防线,其性能与安全性备受关注。其中,电磁兼容性(EMC)测试是净水器产品上市前不可或缺的一环,它直接关系到产品在复杂电磁环境中的稳定运行及不对其…

SpeechCraf论文学习

Abstract 核心问题 挑战 语音风格包含细微的多样化信息(如情感、语调、节奏),传统基于标签/模板的标注方法难以充分捕捉,制约了语音-语言多模态模型的性能。 数据瓶颈: 大规模数据收集与高质量标注之间存在矛盾&…

Work【2】:PGP-SAM —— 无需额外提示的自动化 SAM!

文章目录 前言AbstractIntroductionMethodsContextual Feature ModulationProgressive Prototype RefinementPrototype-based Prompt Generator ExperimentDatasetsImplementation DetailsResults and AnalysisAblation Study 总结 前言 和大家分享一下我们发表在 ISBI 2025 上…

数据安全之策:备份文件的重要性与自动化实践

在信息化高速发展的今天,数据已成为企业运营和个人生活中不可或缺的重要资源。无论是企业的财务报表、客户资料,还是个人的家庭照片、学习笔记,数据的丢失或损坏都可能带来无法挽回的损失。因此,备份文件的重要性日益凸显&#xf…

uniapp+Vue3 组件之间的传值方法

一、父子传值&#xff08;props / $emit 、ref / $refs&#xff09; 1、props / $emit 父组件通过 props 向子组件传递数据&#xff0c;子组件通过 $emit 触发事件向父组件传递数据。 父组件&#xff1a; // 父组件中<template><view class"container">…

blender使用初体验(甜甜圈教程)

使用blender 建模了甜甜圈&#xff0c;时间空闲了&#xff0c;但愿能创建点好玩的吸引人的东西

大模型学习笔记------Llama 3模型架构之旋转编码(RoPE)

大模型学习笔记------Llama 3模型架构之旋转编码&#xff08;RoPE&#xff09; 1、位置编码简介1.1 绝对位置编码1.2 相对位置编码 2、旋转编码&#xff08;RoPE&#xff09;2.1 基本概念---旋转矩阵2.2 RoPE计算原理2.2.1 绝对位置编码2.2.2 相对位置编码 3、旋转编码&#xf…

04 1个路由器配置一个子网的dhcp服务

前言 这是最近一个朋友的 ensp 相关的问题, 这里来大致了解一下 ensp, 计算机网络拓扑 相关基础知识 这里一系列文章, 主要是参照了这位博主的 ensp 专栏 这里 我只是做了一个记录, 自己实际操作了一遍, 增强了一些 自己的理解 当然 这里仅仅是一个 简单的示例, 实际场景…

安装open-webui

open-webui是一个开源的大语言模型交互界面 前提&#xff1a;Ollama已安装&#xff0c;并下载了deepseek-r1:1.5b模型 拉取镜像 docker pull ghcr.io/open-webui/open-webui:main 配置docker-compose.yml services:open-webui:image: ghcr.io/open-webui/open-webui:mainv…

HCIA-11.以太网链路聚合与交换机堆叠、集群

链路聚合背景 拓扑组网时为了高可用&#xff0c;需要网络的冗余备份。但增加冗余容易后会出现环路&#xff0c;所以我们部署了STP协议来破除环路。 但是&#xff0c;根据实际业务的需要&#xff0c;为网络不停的增加冗余是现实需要的一部分。 那么&#xff0c;为了让网络冗余…

Amazon RDS ProxySQL 探索(一)

:::info &#x1f4a1; 在日常开发中&#xff0c;开发者们会涉及到数据库的连接&#xff0c;在使用Amazon RDS数据库时&#xff0c;若使用集群模式或者多数据库时&#xff0c;会出现一写多读多个Endpoint&#xff0c;在实际开发中&#xff0c; 开发者们配置数据库连接通常希望走…

200多种算法应用于二维和三维无线传感器网络(WSN)覆盖场景

2.1 二元感知模型 在当前无线传感器网络&#xff08;WSN&#xff09;覆盖场景中&#xff0c;最常见且理想的感知模型是二元感知模型[27]。如图2所示&#xff0c; Q 1 Q_1 Q1​和 Q 2 Q_2 Q2​代表平面区域内的两个随机点。 Q 1 Q_1 Q1​位于传感器的检测区域内&#xff0c;其感…

模拟类似 DeepSeek 的对话

以下是一个完整的 JavaScript 数据流式获取实现方案&#xff0c;模拟类似 DeepSeek 的对话式逐段返回效果。包含前端实现、后端模拟和详细注释&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><titl…

Flutter PopScope对于iOS设置canPop为false无效问题

这个问题应该出现很久了&#xff0c;之前的组件WillPopScope用的好好的&#xff0c;flutter做优化打算“软性”处理禁用返回手势&#xff0c;出了PopScope&#xff0c;这个组件也能处理在安卓设备上的左滑返回事件。但是iOS上面左滑返回手势禁用&#xff0c;一直无效。 当然之…

SpringBoot + ResponseBodyEmitter 实时异步流式推送,优雅!

ChatGPT 的火爆&#xff0c;让流式输出技术迅速走进大众视野。在那段时间里&#xff0c;许多热爱钻研技术的小伙伴纷纷开始学习和实践 SSE 异步处理。 我当时也写过相关文章&#xff0c;今天&#xff0c;咱们换一种更为简便的方式来实现流式输出&#xff0c;那就是 ​​Respon…

网络运维学习笔记(DeepSeek优化版) 016 HCIA-Datacom综合实验01

文章目录 综合实验1实验需求总部特性 分支8分支9 配置一、 基本配置&#xff08;IP二层VLAN链路聚合&#xff09;ACC_SWSW-S1SW-S2SW-Ser1SW-CoreSW8SW9DHCPISPGW 二、 单臂路由GW 三、 vlanifSW8SW9 四、 OSPFSW8SW9GW 五、 DHCPDHCPGW 六、 NAT缺省路由GW 七、 HTTPGW 综合实…

02 windows qt配置ffmpeg开发环境搭建

版本说明 首先我使用ffmpeg版本是4.2.1 QT使用版本5.14.2 我选择是c编译 在02Day.pro⾥⾯添加ffmpeg头⽂件和库⽂件路径 win32 { INCLUDEPATH $$PWD/ffmpeg-4.2.1-win32-dev/include LIBS $$PWD/ffmpeg-4.2.1-win32-dev/lib/avformat.lib \$$PWD/ffmpeg-4.2.1-win32-dev/l…