LoginSignup
7
4

More than 3 years have passed since last update.

UnrealC++でUE4の標準ライブラリでダイナミックリンク

Last updated at Posted at 2020-02-03

はじめに

最近、UE4の標準ライブラリでダイナミックリンクライブラリをダイナミックリンクさせる方法を見つけたのでご紹介します。
ダイナミックリンクライブラリやダイナミックリンクについては、以下の記事で分かりやすく解説されています。

VC++ DLLの呼び出しと解放

つくるもの

1.PNG

BPから自作のダイナミックリンクライブラリ(以下DLL)の関数を使用するノードを作成します。

つくってみる

まずは、DLLを作成します。作り方については「はじめに」でご紹介した記事を参照してください。

DllTest.cpp
extern "C" __declspec(dllexport) int PlusInt(int x, int y)
{
    return (x + y);
}

BPから使用する関数は上記の関数です。2つの整数を足した値を返します。

次に作成したDLLをロードして関数を実行できるようにする部分を作成します。
今回はDLLのロードやアンロードなどの処理をモジュールクラスに実装します。

TestPlugin.h
#pragma once

#include "Modules/ModuleManager.h"

typedef int(*PlusInt)(int X, int Y);

class FTestPluginModule : public IModuleInterface
{
private:
    //ロードするDllのポインタ
    void* ModulePtr;

    //Dllから取得する関数のポインタ
    PlusInt PlusIntPtr;

public:
    /** IModuleInterface implementation */
    virtual void StartupModule() override;
    virtual void ShutdownModule() override;

    int ExecPlusInt(int X, int Y);
};

まずはヘッダーファイルから見ていきましょう。
ロードした関数を実行する関数とDLLのポインタ、ロードする関数のポインタを定義します。
DLLのロードとアンロードはモジュールの開始時と終了時に行います。

TestPlugin.cpp
#include "TestPlugin.h"
#include "Misc/Paths.h"

#define LOCTEXT_NAMESPACE "FTestPluginModule"

void FTestPluginModule::StartupModule()
{
    //dllファイルのパスを取得
    FString DllPath = FPaths::ConvertRelativePathToFull(FPaths::Combine(FPaths::ProjectPluginsDir(), TEXT("TestPlugin"), TEXT("ThirdParty")));
#ifdef _WIN64
    DllPath = FPaths::Combine(DllPath, TEXT("Win64"));
#elif _WIN32
    DllPath = FPaths::Combine(DllPath, TEXT("Win32"));
#endif
    DllPath = FPaths::Combine(DllPath, TEXT("DllTest.dll"));

    //モジュールをロード
    ModulePtr = FPlatformProcess::GetDllHandle(*DllPath);
    if (ModulePtr == nullptr)
    {
        UE_LOG(LogTemp, Fatal, TEXT("Failed to load module"));
    }

    //関数ポインタを取得
    PlusIntPtr = (PlusInt)FPlatformProcess::GetDllExport(ModulePtr, TEXT("PlusInt"));
    if (PlusIntPtr == nullptr)
    {
        UE_LOG(LogTemp, Fatal, TEXT("Failed to get function pointer"));
    }

    UE_LOG(LogTemp, Log, TEXT("Dll loaded"));
}

void FTestPluginModule::ShutdownModule()
{
    FPlatformProcess::FreeDllHandle(ModulePtr);
    UE_LOG(LogTemp, Log, TEXT("Dll unloaded"));
}

int FTestPluginModule::ExecPlusInt(int X, int Y)
{
    return PlusIntPtr(X, Y);
}

#undef LOCTEXT_NAMESPACE

IMPLEMENT_MODULE(FTestPluginModule, TestPlugin)

次に実装ファイルを見ていきましょう。
まず、DLLのロードやアンロードなどを行うのはFPlatformProcessクラスです。
DLLの操作については以下の関数を使用します。

操作 関数
DLLのロード FPlatformProcess::GetDllHandle
関数ポインタの取得 FPlatformProcess::GetDllExport
DLLのアンロード FPlatformProcess::FreeDllHandle

処理の流れは「はじめに」でご紹介した記事にあるWIN32APIを利用した場合と変わりません。

DLLのファイルパスを組み立て、DLLをロードし、関数ポインタを取得する、という流れです。
最後にロードしたDLLをアンロードします。

最後にBPから利用できるようBlueprintFunctionLibraryを作成します。

TestPluginBPLibrary.h
UFUNCTION(BlueprintCallable, Category = "TestPlugin")
static int PlusInt_DLL(int X, int Y);
TestPluginBPLibrary.cpp
int UTestPluginBPLibrary::PlusInt_DLL(int X, int Y)
{
    FTestPluginModule& TestPluginModule = FModuleManager::LoadModuleChecked<FTestPluginModule>(FName("TestPlugin"));
    return TestPluginModule.ExecPlusInt(X, Y);
}

プロジェクトをビルドしてBPで以下のような処理を組み、実行すると2つの整数の合計が表示されるはずです。
2.PNG
3.PNG

おわりに

ダイナミックリンクは外部APIを使用する際に利用する機会があるのではないでしょうか。
WIN32APIでも同じことはできますが、UE4のライブラリを使用することでWindowsだけでなくMacやLinuxでも動作するようになります。
各プラットフォームでの処理が気になるのであればソースコードを見ているのも面白いかもしれません。

この記事で紹介したプロジェクトは以下でダウンロードできます。
https://github.com/Naotsun19B/DLL_DynamicLink

7
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4