UE4中引用第三方库和一般C++项目是有区别的。下面主要介绍lib静态库和dll动态库的引用:
Demo调试工具:UE4.15.3 、VS2015
新建UE4项目
首先在UE4中新建一个空的C++项目,命名为“JNI_Test”,新建一个C++类,继承自BlueprintFunctionLibrary,命名为“LinkDllBFL”,之后在这定义静态全局函数实现第三方库函数的调用。在JNI_Test项目目录下新建两个文件夹Resources和ThirdPart用于存放后文中的两种第三方库。
lib静态链接库的引用
UE4中lib静态库的引用需要依赖UBT(Unreal Building System)系统,所以需要在Build.cs中实现。
创建lib
在VS中创建新Win32项目,命名“LibTest”,程序类型为静态连接库。在解决方案中添加名为“MyLib”的类:
Mylib.h
#pragma once
//通过半径计算面积
float getCircleArea(float radius);
Mylib.cpp
#include "stdafx.h"
#include "MyLib.h"
float getCircleArea(float radius)
{
return 3.14159265 * (radius * radius);
}
选择x64编译生成解决方案,在项目文件夹中找到x64下的“LibTest.lib”和”MyLib.h”,此处将这两个文件复制到UE4项目“JNI_Test”的“JNI_Test/ThirdPart/x64”目录中。
修改Build.cs
接下来,打开项目C++代码,开始修改Build.cs:
// Fill out your copyright notice in the Description page of Project Settings.
using UnrealBuildTool;
using System;
using System.IO;
public class JNI_Test : ModuleRules
{
private string ThirdPartPath
{
//通过get方法获得ModuleDirectory上两级的ThirdPart目录。
//ModuleDirectory指的是Build.cs所在的目录
get
{
return Path.GetFullPath(Path.Combine(ModuleDirectory, "../../ThirdPart"));
}
}
//加载lib(此处判断了平台信息,预留了win32的接口)
private bool LoadThirdPartLib(TargetInfo Target)
{
if ((Target.Platform == UnrealTargetPlatform.Win64) || (Target.Platform == UnrealTargetPlatform.Win32))
{
string platformStr = Target.Platform == UnrealTargetPlatform.Win64 ? "x64" : "x86";
//得到lib地址
string lib_path = Path.Combine(ThirdPartPath, platformStr, "LibTest.lib");
//添加lib库到includepaths
PublicAdditionalLibraries.Add(lib_path);
PrivateIncludePaths.Add(Path.Combine(ThirdPartPath, platformStr));
PublicIncludePaths.Add(Path.Combine(ThirdPartPath, platformStr));
return true;
}
return false;
}
public JNI_Test(TargetInfo Target)
{
LoadThirdPartLib(Target);
PublicIncludePaths.AddRange(new string[] { "JNI_Test/Public" });
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" });
PrivateDependencyModuleNames.AddRange(new string[] { });
// Uncomment if you are using Slate UI
// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
// Uncomment if you are using online features
// PrivateDependencyModuleNames.Add("OnlineSubsystem");
// To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
}
}
修改完成之后静态库的引入就完成了,是不是很简单。接下来在需要使用lib库中函数的头文件中添加#include “MyLib.h”即可调用lib库中的getCircleArea函数了。
库函数调用
LinkDllBFL.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "Kismet/BlueprintFunctionLibrary.h"
#include "MyLib.h"
#include "LinkDllBFL.generated.h"
/**
*
*/
UCLASS()
class JNI_TEST_API ULinkDllBFL : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, Category = "Lib")
static float circleArea(float radius);
};
LinkDllBFL.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "JNI_Test.h"
#include "LinkDllBFL.h"
//调用lib库中getCircleArea函数
float ULinkDllBFL::circleArea(float radius)
{
return getCircleArea(radius);
}
生成或者compile编译项目。
蓝图编辑,Play
之后我们在UE4编辑器中创建一个JNI_TestGameModeBase的蓝图类“MyJNI_TestGameModeBase”,在MyJNI_TestGameModeBase中编辑如下:
然后点击Play运行项目,运行结果如下:
dll动态链接库的引用
动态链接库dll的引用与静态链接库不同,不需要依赖UBT系统,直接在C++代码中动态引入即可。
步骤如下:
创建dll
在VS中创建新Win32项目,命名“DllTest”,程序类型为dll动态连接库。在解决方案中添加名为“MyDllTest”的类:
MyDllTest.h
#pragma once
#define DLL_EXPORT __declspec(dllexport)//定义dll的函数导出接口
#ifdef __cplusplus
extern "C"
{
#endif
float DLL_EXPORT getCircleArea(float radius);
#ifdef __cplusplus
}
#endif
MyDllTest.cpp
#include "MyDllTest.h"
float DLL_EXPORT getCircleArea(float radius)
{
return float(3.14159265 * (radius * radius));
}
依然选择x64编译解决方案DllTest。在DllTest\x64\Debug 中找到生成的“DllTest.dll”文件,复制到UE4项目的JNI_Test\Resources 目录下。
之后开始在UE4项目的C++代码中修改:
修改LinkDllBFL类
LinkDllBFL.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "Kismet/BlueprintFunctionLibrary.h"
#include "MyLib.h"
#include "LinkDllBFL.generated.h"
/**
*
*/
UCLASS()
class JNI_TEST_API ULinkDllBFL : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
//调用lib库中getCircleArea函数
UFUNCTION(BlueprintCallable, Category = "Lib")
static float circleArea(float radius);
UFUNCTION(BlueprintCallable, Category = "DLL")
static bool importDLL(FString folder, FString name);
UFUNCTION(BlueprintCallable, Category = "DLL")
static bool importMethodGetCircleArea();
UFUNCTION(BlueprintCallable, Category = "DLL")
static float getCircleAreaFromDll(float radius);
UFUNCTION(BlueprintCallable, Category = "DLL")
static void freeDLL();
};
LinkDllBFL.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "JNI_Test.h"
#include "LinkDllBFL.h"
typedef float(*_getCircleArea)(float radius);//定义一个函数指针来存储dll中的getCircleArea函数原型
_getCircleArea m_getCircleAreaFromDll;
void *dllHandle;
//加载DLL
bool ULinkDllBFL::importDLL(FString folder, FString name)
{
FString filePath = *FPaths::GameDir() + folder + "/" + name;
if (FPaths::FileExists(filePath))
{
dllHandle = FPlatformProcess::GetDllHandle(*filePath);//得到dll句柄
if (dllHandle != NULL)
{
return true;
}
}
return false;
}
//从DLL中得到函数getCircleArea
bool ULinkDllBFL::importMethodGetCircleArea()
{
if (dllHandle != NULL)
{
m_getCircleAreaFromDll = NULL;
FString procName = "getCircleArea";
m_getCircleAreaFromDll = (_getCircleArea)FPlatformProcess::GetDllExport(dllHandle, *procName);
if (m_getCircleAreaFromDll != NULL)
{
return true;
}
}
return false;
}
//调用从DLL中传入的getCircleArea函数
float ULinkDllBFL::getCircleAreaFromDll(float radius)
{
if (m_getCircleAreaFromDll != NULL)
{
float out = float(m_getCircleAreaFromDll(radius));//调用dll函数
return out;
}
return -32202.0f;//返回错误
}
//卸载DLL
void ULinkDllBFL::freeDLL()
{
if (dllHandle != NULL)
{
m_getCircleAreaFromDll = NULL;
FPlatformProcess::FreeDllHandle(dllHandle);
dllHandle = NULL;
}
}
float ULinkDllBFL::circleArea(float radius)
{
return getCircleArea(radius);
}
此处我们在LinkDllBFL中实现了4个静态全局函数,分别实现了加载dll、得到dll函数、调用dll函数、卸载dll的功能,之后我们还是来到UE4编辑器中用蓝图实现函数的调用。
蓝图编辑,Play
编译保存之后,Play!!
得到了和上文lib相同的结果:
参考文章:
https://wiki.unrealengine.com/Linking_Static_Libraries_Using_The_Build_System
https://wiki.unrealengine.com/Linking_Dlls