UE5.2 C++插件中调用C#第三方库

C#类库

因为Windows10自带.net framework 4.6.2

从Nuget库中安装 DllExport

具体代码:

Class1.cs

cs 复制代码
using System;

using System.Runtime.InteropServices; // 必须引用

namespace donetFramework462_dll_1
{
    public class Class1
    {

        // 1. 打印 Hello World
        // CallingConvention.Cdecl 是 C 风格导出的标准调用约定
        [DllExport("HelloWorld", CallingConvention = CallingConvention.Cdecl)]
        public static void HelloWorld()
        {
            // 注意:Console.WriteLine 在 UE 的 Log 窗口看不到,但你可以通过调试确认
            Console.WriteLine("Hello World from C# DLL!");
        }

        // 2. 两个整数乘法
        [DllExport("Multiply", CallingConvention = CallingConvention.Cdecl)]
        public static int Multiply(int a, int b)
        {
            return a * b;
        }

    }
}

编译结果:

cpp 复制代码
1>------ 已启动全部重新生成: 项目: donetFramework462_dll_1, 配置: Debug x64 ------
已还原 K:\Project52\donetFramework462_dll_1\donetFramework462_dll_1\donetFramework462_dll_1.csproj (用时 1.13 秒)。
1>  donetFramework462_dll_1 -> K:\Project52\donetFramework462_dll_1\donetFramework462_dll_1\bin\x64\Debug\donetFramework462_dll_1.dll

找一个查看dll导出符号的软件,比如lucasg/Dependencies: A rewrite of the old legacy software "depends.exe" in C# for Windows devs to troubleshoot dll load dependencies issues.

UE插件

新建一个UE C++工程

然后新建一个C++蓝图插件

在路径:K:\Project52\PrueCP\Plugins\zk_donotFramework462_uePlugin\Source

cs 复制代码
K:.
├───ThirdParty
│   └───CSharpLibrary
│       └───x64
└───zk_donotFramework462_uePlugin
    ├───Private
    └───Public

在Source目录下添加文件夹 ThirdParty

然后新建文本文件;文件名:MyCSharpLib.Build.cs

cs 复制代码
using System.IO;
using UnrealBuildTool;

public class MyCSharpLib : ModuleRules
{
    public MyCSharpLib(ReadOnlyTargetRules Target) : base(Target)
    {
        Type = ModuleType.External; // 声明这是一个外部库

        if (Target.Platform == UnrealTargetPlatform.Win64)
        {
            // 使用更健壮的路径获取方式
            // 假设 Build.cs 在 CSharpLibrary 文件夹里
            string LibraryDirectory = ModuleDirectory;

            // 确保这里包含了 "x64"
            string DllName = "donetFramework462_dll_1.dll";
            string DllPath = Path.Combine(LibraryDirectory, "x64", DllName);

            // 如果路径确实不对,我们在这里做个补偿(强制检查层级)
            if (!File.Exists(DllPath))
            {
                // 尝试补齐可能缺失的 CSharpLibrary 目录
                DllPath = Path.Combine(LibraryDirectory, "CSharpLibrary", "x64", DllName);
            }

            // 1. 添加运行时依赖(用于打包)
            RuntimeDependencies.Add(DllPath);

            // 2. 这里的宏定义非常关键,我们需要确保它是一个规范的 Windows 全路径
            string FixedPath = DllPath.Replace("\\", "/");
            PublicDefinitions.Add(string.Format("CSHARP_DLL_PATH=TEXT(\"{0}\")", FixedPath));

            System.Console.WriteLine("--- C# DLL Path Defined: " + FixedPath);
        }

    }
}

实际的dll文件,放在目录:\ThirdParty\CSharpLibrary\x64
然后在自己新建的插件 你的插件名称.Build.cs

cs 复制代码
// Copyright Epic Games, Inc. All Rights Reserved.

using UnrealBuildTool;

public class zk_donotFramework462_uePlugin : ModuleRules
{
	public zk_donotFramework462_uePlugin(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
		
		PublicIncludePaths.AddRange(
			new string[] {
				// ... add public include paths required here ...
			}
			);
				
		
		PrivateIncludePaths.AddRange(
			new string[] {
				// ... add other private include paths required here ...
			}
			);
			
		
		PublicDependencyModuleNames.AddRange(
			new string[]
			{
				"Core",
				// ... add other public dependencies that you statically link with here 
				"MyCSharpLib"	//←添加的库
            }
			);
			
		
		PrivateDependencyModuleNames.AddRange(
			new string[]
			{
				"CoreUObject",
				"Engine",
				"Slate",
				"SlateCore",
				// ... add private dependencies that you statically link with here ...	
				"Projects"  	//←添加的库

            }
			);
		
		
		DynamicallyLoadedModuleNames.AddRange(
			new string[]
			{
				// ... add any modules that your module loads dynamically here ...
			}
			);

    }
}

添加库 MyCSharpLib、Projects 注意//←添加的库的位置。

蓝图库

然后是调用这个c#库的步骤,我们新建一个BlueprintFunctionLibrary蓝图库

头文件如下:

cpp 复制代码
#pragma once

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

/**
 * 
 */
UCLASS()
class ZK_DONOTFRAMEWORK462_UEPLUGIN_API Uzk_blueprintLib1 : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()
	
	//zk add ---------start----------------
	// --- 1. 定义函数指针类型,必须与 C# 端的签名严格匹配 ---
	typedef void (*_HelloWorldFunc)();
	typedef int (*_MultiplyFunc)(int, int);

public:
	// 暴露给蓝图测试
	UFUNCTION(BlueprintCallable, Category = "CSharpBridge")
	static bool ExecuteCSharpDemo();

private:
	// 静态变量保存句柄,避免重复加载
	static void* CSharpDllHandle;
	//zk add ---------end----------------
	
};

CPP文件如下:

cpp 复制代码
#include "zk_blueprintLib1.h"

//zk add --------start----------------------
#include "HAL/PlatformProcess.h"
#include "Misc/MessageDialog.h"
#include "Logging/LogMacros.h"

// 初始化静态变量
void* Uzk_blueprintLib1::CSharpDllHandle = nullptr;

bool Uzk_blueprintLib1::ExecuteCSharpDemo()
{
	// 1. 确定 DLL 路径
	// 我们优先使用 Build.cs 传过来的宏,它指向的是 Source 目录下的 DLL
	FString DllPath = CSHARP_DLL_PATH;

	UE_LOG(LogTemp, Log, TEXT("Attempting to load DLL from: %s"), *DllPath);

	// 2. 加载 DLL
	if (!CSharpDllHandle)
	{
		if (FPaths::FileExists(DllPath))
		{
			CSharpDllHandle = FPlatformProcess::GetDllHandle(*DllPath);
		}
	}

	if (!CSharpDllHandle)
	{
		uint32 ErrorCode = FPlatformMisc::GetLastError();
		UE_LOG(LogTemp, Error, TEXT("Failed to load C# DLL! System Error Code: %d"), ErrorCode);

		// 常见的错误码:
		// 126: 找不到指定模块 (通常是路径不对或少了依赖库)
		// 193: %1 不是有效的 Win32 应用程序 (通常是 x86 和 x64 混用了)
		return false;
	}

	// 3. 获取函数地址
	// 注意:这里的字符串 "HelloWorld" 和 "Multiply" 必须和 C# [DllExport] 中填的一模一样
	_HelloWorldFunc HelloWorldPtr = (_HelloWorldFunc)FPlatformProcess::GetDllExport(CSharpDllHandle, TEXT("HelloWorld"));
	_MultiplyFunc MultiplyPtr = (_MultiplyFunc)FPlatformProcess::GetDllExport(CSharpDllHandle, TEXT("Multiply"));

	// 4. 安全调用
	if (HelloWorldPtr)
	{
		HelloWorldPtr(); // 调用 C# 的打印逻辑
		UE_LOG(LogTemp, Log, TEXT("C# HelloWorld function called successfully!"));
	}
	else
	{
		UE_LOG(LogTemp, Warning, TEXT("Could not find HelloWorld function in DLL."));
	}

	if (MultiplyPtr)
	{
		int Result = MultiplyPtr(5, 8); // 调用 C# 的乘法
		UE_LOG(LogTemp, Log, TEXT("C# Multiply Result (5 * 8): %d"), Result);

		// 弹窗反馈,直观看到结果
		FMessageDialog::Open(EAppMsgType::Ok, FText::FromString(FString::Printf(TEXT("C# Multiply Result: %d"), Result)));
	}

	return true;
}

//zk add --------end----------------------

编译结果:

cpp 复制代码
1>Building 4 actions with 4 processes...
1>[1/4] Compile [x64] Module.zk_donotFramework462_uePlugin.cpp
1>[2/4] Link [x64] UnrealEditor-zk_donotFramework462_uePlugin.lib
1>  正在创建库 K:\Project52\PrueCP\Plugins\zk_donotFramework462_uePlugin\Intermediate\Build\Win64\x64\UnrealEditor\Development\zk_donotFramework462_uePlugin\UnrealEditor-zk_donotFramework462_uePlugin.lib 和对象 K:\Project52\PrueCP\Plugins\zk_donotFramework462_uePlugin\Intermediate\Build\Win64\x64\UnrealEditor\Development\zk_donotFramework462_uePlugin\UnrealEditor-zk_donotFramework462_uePlugin.exp
1>[3/4] Link [x64] UnrealEditor-zk_donotFramework462_uePlugin.dll
1>  正在创建库 K:\Project52\PrueCP\Plugins\zk_donotFramework462_uePlugin\Intermediate\Build\Win64\x64\UnrealEditor\Development\zk_donotFramework462_uePlugin\UnrealEditor-zk_donotFramework462_uePlugin.suppressed.lib 和对象 K:\Project52\PrueCP\Plugins\zk_donotFramework462_uePlugin\Intermediate\Build\Win64\x64\UnrealEditor\Development\zk_donotFramework462_uePlugin\UnrealEditor-zk_donotFramework462_uePlugin.suppressed.exp
1>[4/4] WriteMetadata PrueCPEditor.target
1>Total time in Parallel executor: 3.60 seconds
1>Total execution time: 5.88 seconds
========== 生成: 1 成功,0 失败,0 最新,0 已跳过 ==========

在UE工程里使用蓝图节点:

调用结果如下:

相关推荐
hetao17338372 小时前
2026-01-16~19 hetao1733837 的刷题笔记
c++·笔记·算法
玖釉-2 小时前
[Vulkan 学习之路] 29 - 加载模型 (Loading Models)
c++·windows·图形渲染
HelloWorld1024!2 小时前
C++中链表的虚拟头结点:应用场景与使用时机
网络·c++·链表
fakerth2 小时前
【C++】【Linux】从零实现日志库:LogLib 设计与实现详解
c++·日志库
大闲在人2 小时前
Trae builder 实战: 让 C++ 函数像 Python 一样返回多个值
c++·python·ai编程
txinyu的博客3 小时前
手写 C++ 高性能 Reactor 网络服务器
服务器·网络·c++
枫叶丹43 小时前
【Qt开发】Qt系统(八)-> Qt UDP Socket
c语言·开发语言·c++·qt·udp
一颗青果3 小时前
c++的异常机制
java·jvm·c++
程序猿编码3 小时前
无状态TCP技术:DNS代理的轻量级实现逻辑与核心原理(C/C++代码实现)
c语言·网络·c++·tcp/ip·dns
阿蒙Amon3 小时前
C#每日面试题-简述类成员
开发语言·c#