UE4之整合第三方库

UE4的第三方库,大家都建议使用插件进行整合,那么我也尝试一下插件整合。

首先先写一个C++的动态库:

在AddSdk.h的头文件里面,定义一个函数:

__declspec(dllimport) int Test_Add(int a, int b);

实现函数如下:

__declspec(dllexport) int Test_Add(int a, int b)
{
    return a + b;
}

编译之后,会生成一个动态库

然后在UE4里面添加一个空的插件SimplePlug

UE4之整合第三方库_第1张图片

 

在Source文件夹下面新建一个文件夹ThirdParty

UE4之整合第三方库_第2张图片

 在include里面放置头文件的定义,在lib里面放置lib文件和dll文件

然后需要在SimplePlug.Build.cs里面设置一下

UE4之整合第三方库_第3张图片

 整个代码如下:

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

using System.IO;
using UnrealBuildTool;

public class SimplePlug : ModuleRules
{
	string ThirdPartyPath
    {
		get
        {
			return Path.GetFullPath(Path.Combine(ModuleDirectory, "../ThirdParty/"));
        }
    }

	public SimplePlug(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 ...
			}
			);
			
		
		PrivateDependencyModuleNames.AddRange(
			new string[]
			{
				"CoreUObject",
				"Engine",
				"Slate",
				"SlateCore",
				// ... add private dependencies that you statically link with here ...	
			}
			);
		
		
		DynamicallyLoadedModuleNames.AddRange(
			new string[]
			{
				// ... add any modules that your module loads dynamically here ...
			}
			);

		string includePath = Path.Combine(ThirdPartyPath, "include");
		PublicIncludePaths.Add(includePath);

		string LibPath = Path.Combine(ThirdPartyPath, "lib");
		PublicAdditionalLibraries.Add(Path.Combine(LibPath,"X64", "AddDll.lib"));
		PublicDelayLoadDLLs.Add(Path.Combine(LibPath, "X64", "AddDll.dll"));

	}
}

上述代码主要实现头文件的引入,lib文件的依赖 以及动态库的依赖。

最后新建一个AMyActor

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


#include "MyActor.h"
#include "AddSdk.h"
// Sets default values
AMyActor::AMyActor()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

}

// Called when the game starts or when spawned
void AMyActor::BeginPlay()
{
	Super::BeginPlay();
	UE_LOG(LogTemp, Log, TEXT("Your message =%i"),Test_Add(1,2));
}

// Called every frame
void AMyActor::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

最后发现效果不错:符合预期要求

UE4之整合第三方库_第4张图片

*********************************************2020-07-25*************************************

上面的操作存在两个问题:

1、打包之后,无法调用动态库

2、需要手动拷贝动态库到程序当前路径下。

为了解决这两个问题,有研究了一下

增加拷贝函数,实现把动态库拷贝到需要运行的路径下:

输入参数FIlepath 为动态库的全路径

    private void CopyDllAndLibToProjectBinaries(string Filepath, ReadOnlyTargetRules Target)
    {
        string BinariesDirectory = Path.Combine(ModuleDirectory,"../../", "Binaries/ThirdParty", Target.Platform.ToString());

        string Filename = Path.GetFileName(Filepath);

        if (!Directory.Exists(BinariesDirectory))
        {
            Directory.CreateDirectory(BinariesDirectory);
        }

        File.Copy(Filepath, Path.Combine(BinariesDirectory, Filename), true);

        RuntimeDependencies.Add(Path.Combine(BinariesDirectory, Filename));
    }

另外,把动态库的引入修改为延迟加载,把加载放置到启动module里面,这样可以选择合适的路径来加载动态库

		string includePath = Path.Combine(ThirdPartyPath, "include");
		PublicIncludePaths.Add(includePath);

		string LibPath = Path.Combine(ThirdPartyPath, "lib");
		PublicAdditionalLibraries.Add(Path.Combine(LibPath,"X64", "AddDll.lib"));
		PublicDelayLoadDLLs.Add("AddDll.dll");

		CopyDllAndLibToProjectBinaries(Path.Combine(ThirdPartyPath, "lib", "X64", "AddDll.dll"), Target);

 加载和释放动态库

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

#include "SimplePlug.h"
#include "Core.h"
#include "Modules/ModuleManager.h"
#include "Interfaces/IPluginManager.h"


#define LOCTEXT_NAMESPACE "FSimplePlugModule"


void FSimplePlugModule::StartupModule()
{
	// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module

// Get the base directory of this plugin
	FString BaseDir = IPluginManager::Get().FindPlugin("SimplePlug")->GetBaseDir();

	// Add on the relative location of the third party dll and load it
	FString LibraryPath;

	LibraryPath = FPaths::Combine(*BaseDir, TEXT("Binaries/ThirdParty/Win64/AddDll.dll"));

	ExampleLibraryHandle = !LibraryPath.IsEmpty() ? FPlatformProcess::GetDllHandle(*LibraryPath) : nullptr;

	if (ExampleLibraryHandle)
	{
		// Call the test function in the third party library that opens a message box
		
	}
	else
	{
		FMessageDialog::Open(EAppMsgType::Ok, LOCTEXT("ThirdPartyLibraryError", "Failed to load example third party library"));
	}
}

void FSimplePlugModule::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.

// Free the dll handle
	FPlatformProcess::FreeDllHandle(ExampleLibraryHandle);
	ExampleLibraryHandle = nullptr;
}

#undef LOCTEXT_NAMESPACE
	
IMPLEMENT_MODULE(FSimplePlugModule, SimplePlug)

最后发现一直无法编译通过,需要在下面增加“Projects”

		PublicDependencyModuleNames.AddRange(
			new string[]
			{
				"Core",
				// ... add other public dependencies that you statically link with here ...
                "Projects"
            }
			);

至此,可以实现动态库的自动拷贝,以及实现加载不同路径的动态库,以及打包之后可以正常运行。

你可能感兴趣的:(UE4)