在unity下使用dll非常的方便,然而在unreal下。。。不說了都是淚。
本文使用的引擎版本是ue4.21.2
進入正題,我們使用一個插件來管理第三方的Dll和.so。
首先在已經有的項目工程中新建一個插件,
創建好插件后,在項目的目錄下會找到Plugins/YOURplugin目錄,其中內容如下圖所示:(我的插件叫STmobile)
將要添加的Dll和.so復制進ThirdParty目錄下,(當然你可以在ThirdParty下創建合適的文件路徑):
然后打開YOURplugin.build.cs,添加如下代碼:
private string ModulePath
{
get { return ModuleDirectory; }
}
private string ThirdPartyPath
{
get { return Path.GetFullPath(Path.Combine(ModulePath, "../../ThirdParty/")); }
}
public STmobile(ReadOnlyTargetRules Target) : base(Target) { PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; if (Target.Platform == UnrealTargetPlatform.Win64) { PublicDelayLoadDLLs.Add(Path.Combine(ThirdPartyPath, "Win64", "st_mobile.dll")); PublicDelayLoadDLLs.Add(Path.Combine(ThirdPartyPath, "Win64", "STAvatar.dll")); RuntimeDependencies.Add(new RuntimeDependency(Path.Combine(ThirdPartyPath, "Win64", "st_mobile.dll"))); RuntimeDependencies.Add(new RuntimeDependency(Path.Combine(ThirdPartyPath, "Win64", "STAvatar.dll"))); } 。。。。。。。 }
注意路徑不要搞錯哦。.so同理,
public STmobile(ReadOnlyTargetRules Target) : base(Target) { PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; if (Target.Platform == UnrealTargetPlatform.Android) { AdditionalPropertiesForReceipt.Add(new ReceiptProperty("AndroidPlugin", Path.Combine(ModuleDirectory, "STmobile_APL.xml"))); PublicAdditionalLibraries.Add(ThirdPartyPath + "Android/libs/armeabi-v7a/libxxxx.so"); PublicAdditionalLibraries.Add(ThirdPartyPath + "Android/libs/armeabi-v7a/libxxxx2.so"); } }
這里會多添加一個xml文件,這個是干啥的呢?當我們打包android包時,會利用這個文件將.so復制到打包的目錄下,如果沒有這一步,打包出的apk運行時,會crash報找不到libxxx.so的錯誤,這個xml文件要放在YOURplugin.build.cs的同一目錄下,下面是這個xml的主要內容:
<?xml version="1.0" encoding="utf-8"?> <!-- steps to add to build additions --> <root xmlns:android="http://schemas.android.com/apk/res/android"> <!-- init section is always evaluated once per architecture --> <init> <log text="GameFramework init"/> <setBool result="bSupported" value="false"/> <isArch arch="armeabi-v7a"> <setBool result="bSupported" value="true"/> </isArch> </init> <!-- optional files or directories to copy to Intermediate/Android/APK --> <resourceCopies> <isArch arch="armeabi-v7a"> <log text="Copying libxxx.so"/> <copyFile src="$S(PluginDir)/../../ThirdParty/Android/libs/armeabi-v7a/libxxx.so" dst="$S(BuildDir)/libs/armeabi-v7a/libxxx.so" /> </isArch> </resourceCopies> </root>
Ok,前期准備工作完后,關閉工程,重新生成下.sln。
然后就是Dll函數的使用,在ue4工程中怎么使用Dll函數呢?在c++中我們有兩種調用Dll函數的形式:
- 顯式調用
- 隱式調用
這里我們使用顯示調用,首先在YOURplugin.cpp的StartupModule函數中獲得Dll的handle,如插件中的代碼示例,照葫蘆畫瓢即可。
得到handle后,即可顯式調用dll中的函數,示例如下:
static inline FSTmobileModule& Get()
{
return FModuleManager::LoadModuleChecked<FSTmobileModule>("STmobile");
}
static inline int exampleFunc(int a,int b) { #if PLATFORM_WINDOWS if (FSTmobileModule::Get().ST_mobileLibraryHandle) { typedef int(*_exampleFunc)(int a ,int b); _exampleFunc ExampleFunc; FString procName = "dllFuncName"; ExampleFunc = (_exampleFunc)FPlatformProcess::GetDllExport(FSTmobileModule::Get().ST_mobileLibraryHandle, *procName); if (ExampleFunc) { return ExampleFunc(a,b); } } #elif PLATFORM_ANDROID return dllFuncName(model_path, config, &handle); #endif }
調用.so中的函數,直接#include對應的頭文件,然后調用同名函數即可。
如果想在project中調用插件中的函數,在project.build.cs中將YOURplugin包含進來,然后通過
FSTmobileModule::Get().exampleFunc(int a,int b)直接調用即可。記得#include "STmobile.h"哦