1. 程式人生 > >UE4 呼叫第三方庫(C++dll例子)

UE4 呼叫第三方庫(C++dll例子)

1.建立工程時選擇Visual C++>Win32,建立的工程名稱為Test。之後在工程引導中選擇DLL和空工程即可。建立完成之後新增新類。此處命名為Test。點選儲存後,設定BuildSettingReleasex64(對應win64,如果是32為就X86)生成專案,拿到Project/x64/Release下的dll檔案。

2.lib dll檔案和對應的include檔案考到指定目錄中 通常為專案的Plugins/ThirdParty/Win64  (可自定義,比如放在Source下)

3. 新增到工程中 程式碼如 

PublicAdditionalLibraries.Add(lib

目錄 + lib檔名);//載入第三方靜態庫.lib

 PublicIncludePaths.Add(lib標頭檔案目錄);

使用時 在使用的程式碼中直接#include 標頭檔案即可 (有的時候編譯會報兩個連結錯誤 重新編譯一下就好了)

4. 使用dll  程式碼如下

需要現在.build.cs中配置

 PublicDelayLoadDLLs.Add(dll目錄 + dll檔名);
 RuntimeDependencies.Add(new RuntimeDependency(dll
目錄 + dll檔名));

如果該dll有依賴的dll 需要將依賴的dll放在 binariesPath

相應的平臺下 並呼叫上面的程式碼載入進來

5. dll呼叫

呼叫的方法如下:

假設dll函式原型 int add(int a, int b)

則呼叫程式碼中

typedef int(*AddFunc)(int a, int b);
AddFunc tempFunc;

void* pDllHandler = FPlatformProcess::GetDllHandle(*dll路徑);

if (pDllHandler)
{
FString funcName = "add";
tempFunc = (AddFunc)FPlatformProcess::GetDllExport(pDllHandler, *funcName);
check(tempFunc);
int c = tempFunc(2, 3);
}

注意

1.連結靜態庫和動態庫不同的是,靜態連結屬於工程在編譯期間做的事情,因此這塊需要通過cs指令碼完成,而dll動態連結庫的載入是執行期的事,因此需要在cpp檔案中執行。

2.生成庫時設定Releasex64(對應win64,如果是32位就X86)。

3.有的dll載入不了裡面的函式,解決

編寫庫檔案時加上

//判斷如果是C++編譯器

#ifdef __cplusplus
extern "C" 
{
#endif
    namespace WindowsOperate
    {
        class Common
        {
        public:

            static  __declspec(dllexport) double TestAdd(double &a, double& _b);
        };
    }   

#ifdef __cplusplus
}
#endif

編寫庫檔案時另外在原始檔中加上.def模組定義檔案再編譯,

LIBRARY "TestDll"

EXPORTS

    TestAdd @1

    TestAdd2 @2

如圖:

程式碼示例UE4):

TestDll.build.cs:

public class TestDll : ModuleRules
    {
        public TestDll(TargetInfo Target)
        {          
           Type = ModuleType.External;

            //新增庫的標頭檔案
            PublicIncludePaths.AddRange(
                new string[] {
                "Win64/include"
                // ... add public include paths required here ...
                }
            );
           PrivateIncludePaths.AddRange(
                new string[] {
                "Win64/include"
                // ... add other private include paths required here ...
                }
           );
            string VedioIncludePath = ModuleDirectory + "/Win64/include/";
            PublicSystemIncludePaths.Add(VedioIncludePath);
            //新增庫的lib
            string LibPath = Path.Combine(ThirdPartyPath + "/TestDll/Win64/lib/", "TestDll.lib");
            PublicLibraryPaths.Add(LibPath);
            PublicAdditionalLibraries.Add(LibPath);
            //新增執行時庫的Dll            
            string DllPath = Path.Combine(ThirdPartyPath + "/TestDll/Win64/dll/", "TestDll.dll");
            PublicDelayLoadDLLs.Add("TestDll.dll");
            RuntimeDependencies.Add(new RuntimeDependency(DllPath));
        }
        private string ThirdPartyPath
        {
            get { return Path.GetFullPath(Path.Combine(ModuleDirectory, "../../ThirdParty/")); }
        }
    }

cpp:

typedef double(*_dllFun_Add)(double &a, double& _b);
_dllFun_Add t_fun;
void* PdfDllHandle;

FString dllpath = FPaths::GameSourceDir() + "ThirdParty/TestDll/Win64/dll/TestDll.dll";
	PdfDllHandle = FPlatformProcess::GetDllHandle(*dllpath);
	if (PdfDllHandle!=NULL)
	{
		FString funName = "TestAdd";
		t_fun = (_dllFun_Add)FPlatformProcess::GetDllExport(PdfDllHandle, *funName);
		if (t_fun!=NULL)
		{
			double a1 = 1.2f;
			double a2 = 1.3f;
			double a3 = t_fun(a1, a2);
		}		
	}	

//參考連結,android

//呼叫dll並提供藍圖介面(和wiki的一樣)

https://blog.csdn.net/baidu_27276201/article/details/75675836?locationNum=2&fps=1