Visual Studio で 動的ライブラリ(DLL)を利用する
前回は、作成するところまで行いました。
今回は、実際に使ってみたいと思います。
pickles-ochazuke.hatenablog.com
DLL を使うプロジェクトを作成
とくに変わったところはないです。いつも通り作っちゃってください。自分は、空のプロジェクトで作成しました。プロジェクト名は、Project3
です。ついでに main 関数を書くためにソースファイル(main.cpp)を作っておきましょう。
DLL を使うための準備
さて、まずは DLL を使えるようにしないといけません。ざっくり手順を書きますと
- ソリューションに DLL のプロジェクトを追加(プロジェクトは、前回作成済み)
- 使う側に DLL の参照を追加する
- DLL のヘッダファイルがあるディレクトリを追加する
1. ソリューションに DLL のプロジェクトを追加
ソリューションエクスプローラ
に表示されているソリューションを右クリックして、追加
> 既存のプロジェクト
を選択します。
するとエクスプローラが開くので、追加したい DLL のプロジェクトを選びます。ここでは、前回作成したプロジェクト(DLLTest.vcxproj
)を選びました。これでソリューションエクスプローラ
に、先ほど選んだプロジェクトが表示されていると思います。これで追加完了です。
2. 使う側にDLL の参照を追加する
次に、今回作成したプロジェクト(Project3)に参照を追加します。画像で見ていただくと分かりやすいと思いますが、ソリューションエクスプローラ
に表示されている、Project3
の下に参照
があると思います。ここを右クリックして、参照の追加
を選びます。
で、前回作成したプロジェクト名が表示されていると思うので、それにチェックを入れます。
3. DLL のヘッダファイルがあるディレクトリを追加する
Project3
を右クリックして、一番下にあるプロパティ
を選択します。で、構成プロパティ
> C/C++
と選び、追加のインクルードディレクトリ
に追加したい DLL のヘッダファイルがあるディレクトリを選びます。前回作成した DLL の場合、DLLTest.h
があるディレクトリを選びます。これで準備完了です。
DLL を使う
実際に使ってみます。手順 1 ですでにソースファイル(main.cpp)を作ってあると思うので、そこに書いていきましょう。
以下のように書きました。
#include <iostream> #include "../DLLTest/DLLTest.h" int main() { DLLTest::HelloWorld hello; DLLTest::HelloWorld::hello(); hello.world(); std::cout << hello.huga << std::endl; return 0; }
DLLTest.h
のインクルード場所は、環境によって異なると思いますので、注意してください。ビルドをして通ったら、実行してみましょう。あ、実行の前に、メニュー
> プロジェクト
> "プロジェクト名"のプロパティ
を選び、構成プロパティ
> リンカー
> システム
を選びます。で、サブシステム
という欄があるので、コンソール
を選び、OK を押します。
実行すると同じであれば、以下のように表示されると思います。
おわり
以上が DLL の使い方になります。プロジェクトとヘッダファイルが必要になるので、どこか共通の場所を作っておくと良いかもしれません。どう管理するといいんだろう……。
以下を参考にしました。
Visual Studio で 動的ライブラリ(DLL)を作成する
自分へのメモ書き(上の画像に意味はないです)。
ライブラリを自分で作ったことがなかったので、ちょいと作ってみることに。
Visual Studio は 2017 です。あと C++ で書きます。
DLL プロジェクトの作成
まず、いつも通り Visual Studio を起動して、新しいプロジェクト
を作成します。
選ぶプロジェクトの種類ですが、Win32 コンソールアプリケーション
を選びます。
で、名前はてきとうで構いません。
簡単で打ち間違いにくい名前にするといいかもしれません。ここでは、DLLTest
にしました。
OK > 次へ > と進み、アプリケーションの種類
では、DLL
を選びます。
他は、何もいじらなくてOKです。完了を押します。
するとプロジェクトが作成され、ソリューションエクスプローラ
のソースファイル
の下には、dllmain.cpp
, DLLTest.cpp
, stdafx.cpp
があり、ヘッダーファイル
には、stdafx.h
, targetver.h
があります。
それぞれ開くと、中にコメントが書かれているので、読んでおくといいかもしれません。まぁ触るのは、DLLTest.cpp
だけなのですが。
DLL の実装
では、ライブラリを作っていきます。まず、ヘッダーファイル
にファイルを追加します。ここは、いつも通り新しいクラスを追加するときと同じように作れば良いです。ファイル名も同じように自由です。ここでは、DLLTest.h
にしました。
そして、先頭に以下を書きます。
#ifdef DLLTEST_EXPORTS #define DLLTEST_API __declspec(dllexport) #else #define DLLTEST_API __declspec(dllimport) #endif
ここで注意して欲しいのは、ifdef DLLTEST_EXPORTS
です。これは、プロジェクト名によって異なりますので注意です。新しいプロジェクトを DLL として作成したときに、Visual Studio 側が勝手に定義してくれます。その名前は、プロジェクト名(全て大文字)_EXPORTS
となります。今回、プロジェクト名は、DLLTest
だったので、DLLTEST_EXPORTS
となるわけです。
あとは、この下にいつものようにクラスを書いていきます。今回は、以下のように書いてみました。
namespace DLLTest { class HelloWorld { public: int huga; DLLTEST_API HelloWorld(); static DLLTEST_API void hello(); DLLTEST_API void world(); private: int hoge = 0; }; }
各関数の手前に、DLLTEST_API
があります。先頭行で書いた define
です。DLLTEST_EXPORTS
が定義されているので中身は、__declspec(dllexport)
となるはずです。__declspec(dllexport)
と __declspec(dllimport)
の違いは、ちゃんと調べていないですが、DLL を作成するときは、dllexport
で、 DLL を利用するときは、dllimport
だと判断しています。
変数には付けなくても問題ないようです(ここら辺のことは、どこを見たら分かるんですかね……)。
次に、DLLTest.cpp
に書いていきます。全文を載せています。
#include "stdafx.h" #include "DLLTest.h" #include "iostream" namespace DLLTest { HelloWorld::HelloWorld() : hoge(32) { std::cout << "HelloWorld " << hoge << std::endl; } void HelloWorld::HelloWorld::hello() { std::cout << "Hello"; return; } void HelloWorld::HelloWorld::world() { std::cout << "World" << std::endl; return; } }
こちらは、とくに変わらずいつも通りに書いてしまえば問題ありません。気をつけるのは、stdafx.h
は一番最初にインクルードする必要があることです。原因はよく分かっていないですが、他のインクルードの後だと、ビルドが通りませんでした。
ビルドをして成功したら、DLLTest のフォルダ下にある Debug フォルダに DLLTest.dll があると思います。
おわり
以上で DLL の作成は完了です。まだまだ何となくで作っていますが、少しずつ理解を深めていこうと思います。そのときに分かったことがあれば、また記事にしたいですね。何か参考になりそうな資料を教えていただければ幸いです。
次回は、作成した DLL を使ってみたいと思います。
pickles-ochazuke.hatenablog.com
以下を参考にしました。
https://msdn.microsoft.com/ja-jp/library/ms235636.aspx
https://msdn.microsoft.com/ja-jp/library/3y1sfaz2.aspx
抽象基本クラス(Abstract Base Class : ABC)の復習
ファクトリーメソッドを復習しようと思ったら、抽象基本クラスの復習をする羽目になったので、 調べて学んだことをメモ書きします。
抽象クラスとは
概念的なもの。このクラスから実態を持つことは出来ないが、抽象クラス型へのポインタと参照は使用できる。だそうです。
実態を持たないので、継承しないと意味がありません。なので、抽象基本クラスとも言うそうです(自分が読んだ本には、抽象基本クラスと書いてあった)。今後、抽象基本クラスは ABC(Abstract Base Class)
と表記します。
じゃあ、どういうものが ABC かというと、純粋仮想メンバ関数を持つクラスのことを ABC といいます。純粋仮想メンバ関数というのは、以下の様なものです。
virtual void Method() = 0;
純粋仮想メンバは、継承先で必ずオーバーライドしないといけません。つまり継承先で必ず実装しないといけません。ですが、ABC 側で実装をしてはいけない
という意味ではありません。Method()
を .cpp
ファイルで実装するとコンパイルは通り、呼ぶことが可能です。
ABC は実態を持つことは出来ませんが、ABC 型へのポインタを作ることが可能です。
このポインタを使って、ABC を継承した様々なクラスのインスタンスへのポインタを入れることが出来ます。つまり、以下のように書きます。
IBase *instance = new Derived();
IBase は、ABC です。Derived は、 IBase を継承したクラスです。
instance->method()
のように使えば、継承したインスタンスを呼ぶことが出来ます。上記は、Derived のみですが、他に IBase を継承したクラスがあれば、同じように使うことが出来ます。
コンストラクタ、デストラクタ
コンストラクタを仮想化することは出来ませんが、デストラクタは可能です。 つまり以下のように書けます。
virtual ~IBase();
これは、ABC で必ず必要になります。ABC は、実態を持つことはないので、必ず継承されて使われます。しかし、書かなくてもコンパイルは通ります。このときコンパイラは、デフォルトデストラクタを作成しますが、この状態で ABC を継承した Derived 型のポインタを delete
すると、大変なことが起こります。コードで示すと以下のようになります(コンパイルは通らないかもしれません……)。
// 抽象基本クラス class IBase { public: virtual void Method() = 0; }; // 抽象基本クラスを継承したクラス class Derived : public IBase { public: ~Derived(){}; void Method() {}; }; int main() { IBase *instance = new Derived(); instance->Method(); delete instance; return 0; }
このとき、delete で呼ばれるデストラクタは、IBase のデフォルトデストラクタです。継承先のデストラクタは呼ばれません。どうしてかは詳しく説明できないですが、IBase のデストラクタが実態を持っていることが原因であることは分かると思います。 ですので、抽象基本クラスを作るときは、必ずデストラクタに virtual を付けるように気を付けましょう。
キーワード:override
デストラクタには virtual を付けるように気をつけましょうと言いましたが、このミスをコンパイル時に見つける方法があります。それが、override 指定子です。
こいつを付けることで、コンパイラに「今からオーバーライドするよ」と教えることが出来ます。つまり以下のようになります。
// 抽象基本クラスを継承したクラス class Derived : public IBase { public: ~Derived() override {}; void Method() {}; };
と ~Derived()
の後に override
を付けることで、コンパイル時にエラーが発生するようになります(Visual Studio 2017 だとコンパイルする前に赤い波線が出ました)。
もちろんデストラクタだけでなく、メソッドにも付けることが可能です。オーバーライドをするときには、必ず override を付けるようにしましょう。
キーワード:final
今度は、逆にオーバーライドをして欲しくないときの対処法です。override と同じようにメソッドの後ろに final
を付けます。以下のようになります。
virtual int value() final { return value_; };
このように書くことで、継承先がオーバーライドをしようとすると、コンパイラはエラーを発します。処理が今後変わることがないときは、 final
を付けるようにしましょう。
キーワード:delete
最後に delete
を紹介します。これは、delete 演算子ではありません。何と言うのかちょっと調べただけでは分からないですが、このキーワードを使うことで、メソッドやコンストラクタ、デストラクタを削除することが出来ます。
以下のように書きます。
public: IBase() = delete;
public 側で書くことをお勧めします。これはコンパイラが delete であるかどうかよりもアクセスの可否を先に見るためです。private で delete されたメソッドをユーザが使おうとすると メソッドが private であることだけをエラーとして吐くそうです。また他にも利点があるのですが、ここでのメインの話ではないので省きます。詳細は、Effective Modern C++ の項目 11 を見てください。
Effective Modern C++ ―C++11/14プログラムを進化させる42項目
- 作者: Scott Meyers,千住治郎
- 出版社/メーカー: オライリージャパン
- 発売日: 2015/09/18
- メディア: 大型本
- この商品を含むブログ (7件) を見る
おわり
以上、抽象基本クラスの復習でした。 C++11 から使えるようになったキーワードを混ぜることで、安全に継承をすることが出来るようになりそうです。
ここで記載したコードは、以下に上げています。
最後に、参考にした(復習する羽目になった)書籍を貼っておきます。
- 作者: マーティン・レディ
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2013/11/15
- メディア: Kindle版
- この商品を含むブログを見る
C# と .Net Framework で 他の Windows アプリを操作するアプリ
簡単にですが作りました。
経緯
最近、C# を学び始めて .Net Framework
を使うようになったのですが、これがけっこう便利で楽しくて、
ふと、Windows の API なら ハンドル取ってこれそうだなと思い、調べるとすでにやってる人がいたので、
マネをしてみました。
目的
アプリ一つ一つに割り当てられているハンドル(ウィンドウハンドル)を取得して、
外部のアプリからハンドル先に値を送ることでアプリを操作することが目的です。
まだ可能かどうかは分かりませんが、ゲームのテストや同じ操作の繰り返しをプログラムで
制御できればいいなと思って作りました。
こちらを参考にしたので、試したい方はこちらを見た方が早いかと思います。
普通、アプリだと複数のウィンドウやボタンがあるので、操作をするのは難しいのですが、 自分の場合は、ゲームの操作が目的だったので、ハンドルを取ってしまえばあとはコントローラの キーにあたる値を送ることで操作することが可能です。
操作するためのキーの値はこちらを見ればいいかと
Virtual-Key Codes (Windows)
環境
環境は以下です。
- Windows 10
- VisualStudio 2017
以下は、今回使う言語やフレームワーク、その他出てくる技術です。
もし読んでて分からないところがあれば、以下のキーワードを加えて検索するといいかも……?
- C#
- .Net Framework 4.0 以上
- WPF
- Win32API
GUI の作成
WPF で GUI を作ります。 重要な部分ではないので飛ばします。以下のように作りました。
各ボタンの処理
Get Handle
というボタンは、隣にある Process Name
の入力内容を元に関係するアプリを探して、ウィンドウハンドルを取得します。Process Name
は、タスクマネージャを開き、詳細タブに並んでいる .exe
を除いたアプリの名前を入力します。
ボタン入力時の処理は以下です。
private void GetHandleButton_Click(object sender, RoutedEventArgs e) { process = System.Diagnostics.Process.GetProcessesByName(ProcessName.Text); foreach (System.Diagnostics.Process ps in process) { LogBox.Text += ps.Id + ps.MainWindowTitle + ps.MainWindowHandle + "\n"; } }
GetProcessesByName
でアプリのハンドルを取得します。
取得したら、内容をテキストボックスに出力します(これは確認用)。
Button
というボタンは、Message
の内容をハンドル先に送ります。つまり、Message
に操作用の値を書き、
Button
を押すことでアプリを操作します。が、これはまだ未実装です。現状は、予め用意した値を送るようにしています。
IntPtr hWnd = process[0].MainWindowHandle; LogBox.Text += SendMessage(hWnd, 0x0100, 0x20, 0x00);
SendMessage()
で、どう操作したいかを指示しています。その後、確認用にテキストボックスに出力しています。
SendMessage(ハンドル, イベント, 内容1, 内容2)
のように指定します。
イベントは、キーが押された
やキーが離された
、マウスのボタンがクリックされた
などです。内容1,2はイベントに合わせて指定します。何もない場合は 0x00
でいいと思います。
上記だと、hWnd
に、スペースキー
が押された
という情報を送ります。
SendMessage
は、.Net Framework
の API ではなく、Win32API
の API です。これは、以下のように宣言することで使えるようになります。
[System.Runtime.InteropServices.DllImport("user32.dll")] public static extern int SendMessage(IntPtr hWnd, uint Msg, uint wParam, uint lParam);
DllImport
という属性(Attribute)
を使うことで、外部のライブラリを使えるようにしています。
ここら辺は、以下を参照してください。(正直、自分はちゃんと理解出来ていません……)
@IT:.NET TIPS Win32 APIやDLL関数を呼び出すには? - C#
キーワード:Attribute, Reflection, Annotation
これだけのコードで、別のアプリにプログラムで好きなキー入力を行うことができます。
コード
XAML 側のコードがないので、これだけでは動かないのですが、一応全文載せておきます。
using System; using System.Windows; namespace GetHandle { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { System.Diagnostics.Process[] process; public MainWindow() { InitializeComponent(); } private void GetHandleButton_Click(object sender, RoutedEventArgs e) { process = System.Diagnostics.Process.GetProcessesByName(ProcessName.Text); foreach (System.Diagnostics.Process ps in process) { LogBox.Text += ps.Id + ps.MainWindowTitle + ps.MainWindowHandle + "\n"; } } private void MessageButton_Click(object sender, RoutedEventArgs e) { IntPtr hWnd = process[0].MainWindowHandle; LogBox.Text += SendMessage(hWnd, 0x0100, 0x20, 0x00); } [System.Runtime.InteropServices.DllImport("user32.dll")] public static extern int SendMessage(IntPtr hWnd, uint Msg, uint wParam, uint lParam); } }
デモ
ウィンドウハンドル取得して、キー入力をハンドル先に送るアプリを作ったらそのままUE4でも使えた。動画は、スペースキーの値を送ってる #UE4 #UE4Study pic.twitter.com/rdBUnvPXyA
— 漬茶漬け (@tauto_otya) 2017年3月25日
UE4 で http 通信を行う
少し前に UE4 で http 通信をしようと思い、ネットで方法を探していたのですが、 バージョンの違いか、手順が悪いのか、上手くいかず悩んだ末、UE4 の公式ドキュメントの方法で出来たので、その方法をまとめます。
以下、自己責任で行って下さい。
UE4.10 How To Make HTTP GET Request in C++ - Epic Wiki
上記のURLの方法をそのまま行えば出来ます。
ただ、php 周りの説明が分かっている前提なので、その辺補足出来たらいいなと思い、この記事を書くことにしました。
環境
- Windows 10
- UE4.14.3
- VisualStudio 2015
- XAMPP 3.2.2
プロジェクトの作成
まず、新規プロジェクトでC++のタブを選択します。 そして、基本コード(BASIC CODE)を選択します。
すると、VisualStudio が立ち上がると思います。気長に全ファイルを読み込むのを待ちます。
読み込めました? では、ビルドしましょう。
とくに問題が起こらないとは思うので、次に進みます。
アクタの作成
UE4 のエディタで http を取得するアクタを作ります。
まず、コンテンツブラウザの新規追加
を選び、新規 C++ファイル…
を選択します。親クラスは、Actor
を選択します。
ファイル名は何でもいいです。今回は、GetHttpActor
としました。あと、パブリック、プライベートは特に選択しませんでした。
クラスを作成
をクリックして、リコンパイルが終わるのを待ちます。
ソースコードの編集
では、プロジェクトの中身をいじっていきます。
Build.cs
”プロジェクトファイル名”.Build.cs
という名前のファイルが VisualStudio のソリューションエクスプローラー
にあると思います。
今回、自分のプロジェクト名は、MyProject
(つまりデフォルトの名前)にしたので、MyProject.Build.cs
というファイルがあるはずです……ありました。
見つかりましたか? よく探してくださいね。ソリューションエクスプローラーの検索を利用するといいかもしれません。例えば、.Build.cs
で検索してみましょう。Games
のフォルダ内を探して下さい。もう見つかった? お疲れ様です。では、次に行きましょう。
先ほど見つけたファイル(画像だと MyProject.Build.cs
)を開いてください。
MyProject.Build.cs
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore"});
"Http", "Json", "JsonUtilities"
という一文があると思います。バージョンによっては違うかも……。
PublicDependencyModuleNames.AddRange
を探すといいかもしれません。見つけたら、{}内に以下を追加します。
すると以下のようになると思います。
MyProject.Build.cs
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "Http", "Json", "JsonUtilities" });
このファイルはこれで以上です。
Engine.ini
次は、Engine.ini
ファイルを探します。VisualStudio は使いません。そこには表示されないからです。
プロジェクトフォルダが保存されている場所に移動してください。そして、今回のプロジェクト名のフォルダの中に移動します。Saved/Config/Windows
と移動して下さい。もしかしたら Windows
がないかもしれません。Config
以下まで移動したら、Engine.ini
を探して下さい。自分は、MyProject/Saved/Config/Windows
の下に Engine.ini
がありました。そして、てきとうなテキストエディタで開きます。
そして、一番下に以下を追加します。
Engine.ini
[HTTP] HttpTimeout=300 HttpConnectionTimeout=-1 HttpReceiveTimeout=-1 HttpSendTimeout=-1 HttpMaxConnectionsPerServer=16 bEnableHttp=true bUseNullHttp=false HttpDelayTime=0
追加したら、保存して閉じて下さい。またVisualStudio に戻ります。
GetHttpActor.h
http を取得するアクタを作ったと思います。そのヘッダファイルを開きます。
今回だと、GetHttpActor.h
です。
まず、以下のようにインクルードファイルを追加します。
GetHttpActor.h
#include "Runtime/Online/HTTP/Public/Http.h"
public: 以下に次の内容を追加します。
FHttpModule* Http; /* The actual HTTP call */ UFUNCTION() void MyHttpCall(); /*Assign this function to call when the GET request processes sucessfully*/ void OnResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful);
ヘッダファイルは以上です。
GetHttpActor.cpp
次は、ソースファイル GetHttpActor.cpp
をいじります。まず、コンストラクタ AGetHttpActor()
に以下を追加します。
Http = &FHttpModule::Get();
そして BeginPlay()
に以下を追加します。
MyHttpCall();
以下のメンバメソッドを追加します。
GetHttpActor.cpp
/*Http call*/ void AGetHttpActor::MyHttpCall() { TSharedRef<IHttpRequest> Request = Http->CreateRequest(); Request->OnProcessRequestComplete().BindUObject(this, &AGetHttpActor::OnResponseReceived); //This is the url on which to process the request Request->SetURL("http://localhost:8081/WebApi/getint.php"); Request->SetVerb("GET"); Request->SetHeader(TEXT("User-Agent"), "X-UnrealEngine-Agent"); Request->SetHeader("Content-Type", TEXT("application/json")); Request->ProcessRequest(); } /*Assigned function on successfull http call*/ void AGetHttpActor::OnResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful) { //Create a pointer to hold the json serialized data TSharedPtr<FJsonObject> JsonObject; //Create a reader pointer to read the json data TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(Response->GetContentAsString()); //Deserialize the json data given Reader and the actual object to deserialize if (FJsonSerializer::Deserialize(Reader, JsonObject)) { //Get the value of the json object by field name int32 recievedInt = JsonObject->GetIntegerField("customInt"); //Output it to the engine GEngine->AddOnScreenDebugMessage(1, 2.0f, FColor::Green, FString::FromInt(recievedInt)); } }
ひとまずは、コピペで構いません。
お疲れ様です。C++ に追加することは以上で終了です。
ビルドが通るか確認しましょう。
これで、GetHttpActor をレベル上に置けば http を取得してくれるのですが、今の状態で行っても http は取得できません。http を発行してくれるサーバがないからですね。では、サーバの準備をしましょう。
XAMPP
サーバを立てる方法はいろいろありますが、今回は XAMPP を使います。 インストールの方法は、ネット上にたくさんあるので、そちらにお任せします。 例えばこれを見るといいでしょう。
XAMPP を立てるときにセキュリティが気になる人は、セキュリティの設定を行うか、ネット回線を切ってしまいましょう。
たぶん XAMPP を使って Apache を立てるとエラーが発生すると思います。 その場合、以下の記事を見ると解決するかもしれません。
余裕があれば、別記事にまとめたいと思います……。
PHP ファイルの作成
XAMPP を上手く入れることが出来ましたでしょうか? お疲れ様です。あと少しで完了です。では、XAMPP を無事インストールしたので、PHP のファイルを作ります。
以下の内容をコピペして下さい。
getint.php
<?php //Create a variable to be used in $theVar = array('customInt' => 5); //Set the headers header('Content-Type: application/json'); //Encode the variable, and save the encoded string $encoded = json_encode($theVar); //Output it echo $encoded; ?>
そして、getint.php
というファイル名にして保存します。
このファイルを以下に置いて下さい。
C:\xampp\htdocs\WebApi
WebApi フォルダは作る必要があると思います。XAMPP をインストールするときに、保存場所を変更した場合は、 C:\ の下にないかもしれません。getint.php
ファイルを置くことが出来たら、少しだけ C++ ファイルをいじります(Apache のポート番号を変えていなかったら必要ないかも)。
C++ 側の URL を編集
GetHttpActor.cpp
を開いて下さい。
そして、void AGetHttpActor::MyHttpCall()
の中を見ます。
Request->SetURL("http://localhost:8081/WebApi/getint.php");
という一文があると思いますが、この SetURL の中身を変えます。 見ると分かるかもしれませんが、中身は URL を表しています。 注意してほしいのは、 localhost:8081 の 8081 です。Apache のポート番号とここのポート番号が合っていないと、正しく処理することが出来ません(URLの場所が見つからないからです)。
サーバを立てる
SetURL の中身を書き換えたら、XAMPP の Apache の Start のボタンをクリックして下さい。すると Apache の文字の周りが黄緑色みたいになると思います。黄色や赤色だと何か問題が発生していると思います。エラーの内容をコピペして検索してみましょう。
問題がない場合、サーバを立てることに成功しています。実際に確認してみましょう。ブラウザを開いて、以下のように入力します。
例えば、http://localhost:94/ とします(ポート番号は人によって異なります)。すると以下のような画面が表示されます。
SetURL と同じURLを指定してみましょう
http://localhost:94/WebApi/getint.php
すると以下のような文章が出ると思います。
{"customInt":5}
これが出ていれば成功です。
では、VisualStudio の方でビルドをします。成功したら、UE4 エディタに戻り、GetHttpActor
を選択します。右クリックをして、「GetHttpActor に基づくブループリントクラスを作成します。」
を選択します。そして、てきとうなファイル名(自分は、MyGetHttpActor にしました)を設定し、てきとうな場所に作って下さい。そして、
MyGetHttpActor
を開きます。開いたら、コンポーネントを追加で視覚的に置いてあることが分かるようなものを追加しましょう。自分はキューブを追加しました。そしてコンパイルをして、レベル上に配置します。
確認
最後に確認です。
- XAMPP は正常に動作していますか?
- Apache は正常に動作していますか?
- ブラウザを開いて、
http://localhost:94/WebApi/getint.php
にアクセスすると、php のコードが正しく動いていますか? PHP のコードをコピペしていたら {“customInt”:5} のように表示されるはずです。 - VisualStudio は正しくビルド出来ていますか?
- SetURL の中身は
http://localhost:94/WebApi/getint.php
になっていますか? - UE4 のレベル上に GetHttpActor を継承したブループリントクラスのインスタンスが置かれていますか?
では、UE4 エディタのプレイをクリックしましょう。
以下の画像のように文字が表示されるはずです。
無事、http 通信をすることが出来ました。とても小さなことですが、これだけでもいろいろ幅が広がります。長くなりましたが、以上です。 お疲れさまでした。
おわりに
http 周りのソースコード調べないとなぁ……。
あと、分かりづらいところがあればコメントを下さい。