読者です 読者をやめる 読者になる 読者になる

お茶漬けびより

学んだことを整理する場所です。主に、C++, Unreal Engine 4 (UE4) を扱います。

C# と .Net Framework で 他の Windows アプリを操作するアプリ

C# .Net Framework UE4

簡単にですが作りました。

経緯

最近、C# を学び始めて .Net Framework を使うようになったのですが、これがけっこう便利で楽しくて、 ふと、WindowsAPI なら ハンドル取ってこれそうだなと思い、調べるとすでにやってる人がいたので、 マネをしてみました。

目的

アプリ一つ一つに割り当てられているハンドル(ウィンドウハンドル)を取得して、 外部のアプリからハンドル先に値を送ることでアプリを操作することが目的です。
まだ可能かどうかは分かりませんが、ゲームのテストや同じ操作の繰り返しをプログラムで 制御できればいいなと思って作りました。

こちらを参考にしたので、試したい方はこちらを見た方が早いかと思います。

普通、アプリだと複数のウィンドウやボタンがあるので、操作をするのは難しいのですが、 自分の場合は、ゲームの操作が目的だったので、ハンドルを取ってしまえばあとはコントローラの キーにあたる値を送ることで操作することが可能です。

操作するためのキーの値はこちらを見ればいいかと
Virtual-Key Codes (Windows)

環境

環境は以下です。

以下は、今回使う言語やフレームワーク、その他出てくる技術です。
もし読んでて分からないところがあれば、以下のキーワードを加えて検索するといいかも……?

GUI の作成

WPFGUI を作ります。 重要な部分ではないので飛ばします。以下のように作りました。

f:id:pickles-ochazuke:20170326231753p:plain

各ボタンの処理

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 FrameworkAPI ではなく、Win32APIAPI です。これは、以下のように宣言することで使えるようになります。

[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);
    }
}

デモ

Re:ゼロから始めるポインタ入門 #1

C C++ 勉強

前回の続きです。

前回は、準備運動のようなものでしたが、 今回からはちゃんとポインタについて入門していきます。

まずポインタのことを知る前に、二つのことを知っておく必要があります。 16 進数とアドレスです。この二つを説明したあと、最後にポインタについて解説していきます。

16 進数

16 進数を知っている方は、読み飛ばして構いません。逆に知らない方は 2 進数のことを分かっておく必要があります。 2 進数については、前回に書いてあるので、そちらを参照してください。

16 進数とは、2 進数と 10 進数を知っているのであれば大方予想が着くと思いますが、16 の倍数で桁が増える表現方法です。 ですが、数字とは 0 ~ 9 の 10 個の数字です。残り 6 個はどうするかというと…… A ~ F を使います。10 進数では、9 の次が 10 で桁が増えますが、16 進数の場合は、9 の次は A になり桁は増えません。そこから B、C、D …… F と続きます。F は 10 進数で表すと値は何でしょう。数えてみましょう。 9、A(10)、B(11)、C(12)、D(13)、E(14)、F(15)。つまり F15 です。その次は基数の 16 なので、桁が一つ上がります。そう 10 になります。ところで 1010 進数の 10(十)なのか 16 進数 の 10(十六)なのか、2 進数の 10(二)なのか分かりづらいですね。 そこで、分かりやすいように手前に記号を付けます。2 進数の場合は、0b、 10 進数の場合は、0d、 16 進数の場合は 0x です。 b は binary(2 進数) の b。d は decimal(10 進数)の d。x は、Hexadecimal の x です(なんで h じゃないんだろう。hex が x に縮まったのかな……)。整理しましょう。

1000 という数字の手前に記号を付けます。説明のために数値は、10 進数に直しますが、数字だとややこしいので、漢字で解説します。
0b1000:これは、2 進数なので、ですね。
0d1000:これは、10 進数なので、です。
0x1000:これは、16 進数です。デカいですね。16 の 3 乗なので、四千九十六です。
どうでしょうか。整理できましたか? 16 進数は、慣れておくと便利なので、いろいろ自分で計算して練習してみましょう。

10 進数から 2 進数に変換し、2 進数から 16 進数への変換ができるのですが、これは、ネットや本に詳しく書かれているのでそちらを参照してください。

アドレス

では、アドレスについてです。前回、変数の話で値を保持するには器の大きさがあり、場所が必要だと書きました。この場所を管理するための番号があります。それがアドレスです。では、実際にアドレスを見てみましょう。アドレスを見るためには、変数の名前の前に &(アンパサンド) を付けます。

#include <stdio.h>

int main()
{
    int variable;

    printf("address of variable: %p\n", &variable);
    return 0;
}

上記を実行すると、以下のようにアドレスが表示されます。ただし、アドレスの値は毎回変わります。

address of variable: 0x7ffff409cbdc

これは、variable という器が 0x7ffff409cbdc の場所に保持されているということです。次に配列を作って、その配列のアドレスがどうなっているか見てみます。以下のプログラムを作成してください。

#include <stdio.h>
#define ARRAY_MAX (10)

int main()
{
    char array[ARRAY_MAX];
    int  aryi;

    for (aryi=0; aryi<ARRAY_MAX; aryi++) {
        printf("address of array[%d]: %p\n", aryi, &(array[aryi]));
    }
    return 0;
}

では、実行してみましょう。以下のようになりました。

address of array[0]: 0x7fffec172540
address of array[1]: 0x7fffec172541
address of array[2]: 0x7fffec172542
address of array[3]: 0x7fffec172543
address of array[4]: 0x7fffec172544
address of array[5]: 0x7fffec172545
address of array[6]: 0x7fffec172546
address of array[7]: 0x7fffec172547
address of array[8]: 0x7fffec172548
address of array[9]: 0x7fffec172549

アドレスのとこを見て下さい。各アドレスの下の位から 1~3 つ目まで見れば問題ありません。値が 1 ずつ増えてるのが分かります。char 型は、サイズが 1 Byte、つまり 8 bit です。つまり、このアドレスの単位は Byte のようです。試しに型を変えてみましょう。char 型から int 型にしてみると以下のようになりました。

address of array[0]: 0x7fffe297dc40
address of array[1]: 0x7fffe297dc44
address of array[2]: 0x7fffe297dc48
address of array[3]: 0x7fffe297dc4c
address of array[4]: 0x7fffe297dc50
address of array[5]: 0x7fffe297dc54
address of array[6]: 0x7fffe297dc58
address of array[7]: 0x7fffe297dc5c
address of array[8]: 0x7fffe297dc60
address of array[9]: 0x7fffe297dc64

4 ずつ増えていますね。(long)int 型は 4 Byte なので、アドレスの単位は Byte で正しそうです。

アドレスは場所を管理するための番号です。先ほどのプログラムの結果からアドレスは 型のサイズずつ管理しているということですね。

配列の結果を見ると分かりますが、変数は他の変数が占有している場所を利用して値を保持することはできません。中には共有する変数もありますが……今回は無視しましょう。基本的に変数が確保した場所は、その変数専用の場所になります。ですので、その変数が占有しているアドレスに訪れるとその変数の場所にたどり着くことができます。つまり、変数の場所が分かれば、その変数の中にある値を見たり、別の値を変数の中に入れたりできるわけです。そのための方法がポインタです。

ポインタの話に行く前に、一つ遊んでみましょう。何をするかというと足し算です。 以下を実行して下さい。

#include <stdio.h>
#define ARRAY_MAX (3)

int main()
{
    int array[ARRAY_MAX];
    int aryi;

    for (aryi=0; aryi<ARRAY_MAX; aryi++) {
        array[aryi] = aryi;
        printf("address of array[%d]: %p\n", aryi, &(array[aryi]));
    }
    printf("\n");

    printf("array[0] + 1\n");
    printf("%p + %d = %p\n", &(array[0]), 1, (&array[0]) + 1);

    return 0;
}

結果は以下のようになりました。

address of array[0]: 0x7fffe8de9180
address of array[1]: 0x7fffe8de9184
address of array[2]: 0x7fffe8de9188

array[0] + 1
0x7fffe8de9180 + 1 = 0x7fffe8de9184

array[0] のアドレス(0x7fffe8de9180)に 1 を加えると結果は、0x7fffe8de9184 になりました。なんと、4 も増えていますね。次に array の型を int から char にしてみましょう。 結果は、以下のようになりました。

address of array[0]: 0x7fffd307cf50
address of array[1]: 0x7fffd307cf51
address of array[2]: 0x7fffd307cf52

array[0] + 1
0x7fffd307cf50 + 1 = 0x7fffd307cf51

今度は、1 増えています。つまり型によって値の増え方が変わるというわけです。これで中途半端なアドレスを、簡単には指定できないようになってるわけですね。ちなみに、 printf 文内の足し算の処理を以下のようにすると、中途半端なアドレスが作れます。arrayint 型です。

(char*)(&array[0]) + 1

ですが、危険なのと特に意味はないので使う機会はないでしょう。

ポインタ

ポイント(point)という言葉があります。これは、点や先という意味もありますが、向けるや指さすという意味もあります。なのでポインタ(pointer)は、向ける者や指さす者という感じでしょうか。何に指さすかというとアドレスの中にあるモノです。ポインタが指さす先には、何かがあるわけです。実際にポインタを使ってみましょう。

#include <stdio.h>

#define ARRAY_MAX (3)

int main()
{
    int array[ARRAY_MAX];
    int aryi;

    for (aryi=0; aryi<ARRAY_MAX; aryi++) {
        array[aryi] = aryi;
        printf("address of array[%d]: %p\n", aryi, &(array[aryi]));
    }
    printf("\n");

    int* array_ptr;
    array_ptr = &array[0];

    printf("array_ptr has address of array[0]: %p\n", array_ptr);
    printf("array_ptr points %d\n", *array_ptr);

    return 0;
}

結果は以下のようになりました。

address of array[0]: 0x7ffff5947b90
address of array[1]: 0x7ffff5947b94
address of array[2]: 0x7ffff5947b98

array_ptr has address of array[0]: 0x7ffff5947b90
array_ptr points 0

array_ptr = &array[0] によって、ポインタ(array_ptr)に array[0] のアドレスを教えて、そのあとポインタが指し示す場所を見に行っています。*array_ptrで指している場所を見に行けるわけです。

アドレスの最後に足し算をしましたが、これを使えば配列の中を自由に見に行けます。 以下を実行してみましょう。

#include <stdio.h>

#define ARRAY_MAX (3)

int main()
{
    int array[ARRAY_MAX];
    int aryi;

    for (aryi=0; aryi<ARRAY_MAX; aryi++) {
        array[aryi] = aryi;
        printf("address of array[%d]: %p, %d\n", aryi, &(array[aryi]), array[aryi]);
    }
    printf("\n");

    int* array_ptr;
    array_ptr = &array[0];

    for (aryi=0; aryi<ARRAY_MAX; aryi++) {
        printf("array_ptr has address of array[%d]: %p\n", aryi, array_ptr + aryi);
        printf("array_ptr points %d\n", *(array_ptr+aryi));
    }
    return 0;
}

結果は、以下のようになりました。

address of array[0]: 0x7fffed9f3780, 0
address of array[1]: 0x7fffed9f3784, 1
address of array[2]: 0x7fffed9f3788, 2

array_ptr has address of array[0]: 0x7fffed9f3780
array_ptr points 0
array_ptr has address of array[1]: 0x7fffed9f3784
array_ptr points 1
array_ptr has address of array[2]: 0x7fffed9f3788
array_ptr points 2

配列の中を先頭から順番に見れているようです。実は、配列の各要素を指定するときのarray[i]は、*(array + i)の略なんですね。配列は、ポインタというわけです。[] を使わずに array とすると、配列 array の先頭のアドレスを指します。先頭のアドレスとは、&array[0] のことです。つまり array&array[0] は同じ意味です。整理しましょう。

以下は、int array[3] とした場合の説明です。

  • 配列は、ポインタの別の表現方法。
  • &array[0]array は同じアドレスを指す。
  • 配列の要素([] 内の値)は、配列の先頭からどれだけアドレスを増やすかを示すモノ。
  • array[i]*(array + i) は同じ意味。

確認してみましょう。

#include <stdio.h>
#define ARRAY_MAX (3)

int main()
{
    int array[ARRAY_MAX];
    int aryi;
    
    if (&array[0] == array) {
        printf("&array[0] == array\n");
    }

    if (&array[2] == array + 2) {
        printf("&array[2] == array + 2\n");
    }

    array[1] = 100;
    if (array[1] == *(array + 1)) {
        printf("array[1] == *(array + 1)\n");
    }

    return 0;
}

結果は、以下のようになりました。

&array[0] == array
&array[2] == array + 2
array[1] == *(array + 1)

おわりに

今回は、ポインタを入門してみました。配列のくだりはあまり理解しなくても問題ありませんが、 配列とポインタを頭の中で変換できるとポインタの理解が深まる気がします。 ポインタを理解するには、実際にコードを書くしかないと思います。 最低限以下を覚えておけば、ポインタで使われるテクニックはすべて理解可能だと思っています。

  • ポインタの宣言は、int * pointer のように行う。
  • 変数の保持されている場所のアドレスは、& で見ることができる。
  • ポインタの中には、アドレスを入れる。
  • ポインタの手前に * を付けると、アドレス先の中身を見に行く。

Re:ゼロから始めるポインタ入門 #0

C C++ 勉強

仕事でC言語を使っていて、ポインタでたまに分からなくなる時があるので、整理するために書き起こすことにしました。

何回かに分けてポインタを復習していく予定です。
今回は、準備運動なのでポインタとあまり関係ありませんが、知っていると理解しやすいと思い、書きました。

一応断りを入れておきますが、中身の正確さは保証しません。
理解のきっかけにしてもらって、正確な情報は書籍などで入手してください。

環境

まず環境ですが、C言語を書けて実行できるなら何でも構いません。
自分は、

で行っています。

変数と型

知っていたら読み飛ばして大丈夫です。

変数

変数とは、不定値のことです。つまりその時々によって、値が変化するということです。 定数の逆ですね。プログラミング言語の中では、値を入れるための器のようなものです。 C言語だと以下のようにして、定義します。

int variable = 10;

これは、variable という変数に 10 という値を入れたという意味になります。 で、variable の手前にある int というのは、変数の型を決めるためのキーワードです。 int だと、整数の値を入れる専用の器を用意することになります。

他にも文字型や浮動小数点型があります。これらの違いは何かというと、「器の大きさ」と その中に入っている「値の表現の違い」を決めています。 まず、「器の大きさ」ですが、値を入れる場所を作るということは、その場所が必要になります。 その場所はもちろん有限です。いわゆるメモリがその場所になります。その中の一部を借ります。 で、今回の int はどれだけ借りるかというと、4Byte です。 bit で表すと 1Byte8bit なので、 32bit ですね。

文字型の char だと、1Byte です。int の中には 2 種類の型があり short intlong int があります。 short2Bytelong4Byte です。long intint は同じ大きさになります(環境によっては変わるかも)。 他にも型がありますが、気になる方は調べて下さい。

ここからは、正直ポインタと関係はあまりないので読み飛ばして大丈夫です。

次に表現の違いですが、変数の中に入っている値は、すべて 2 進数で表されています。 2 進数とは、0 と 1 で表現する数字です。2 の基数で表現するので 2 進数 なのですが、 あまり気にする必要はないでしょう。

で、先ほどの

int variable = 10;

ですが、10 はマシンから見れば、2 進数 で表すので、1010 です。 これを人でも理解しやすいように 10 進数 で扱えるようにしているに過ぎません。 それで、表現の違いについてですが、この値を型によって意味を変えているだけです。 何が言いたいかというと、中に入っている値は同じでも型によって意味が変わるということです。

では、まず以下のコードをビルドして実行してみましょう。

#include <stdio.h>

int main()
{
    int variable = 65;
    printf("variable: %d\n", variable);
    return 0;
}

実行すると variable: 10 と表示されると思います。
次に以下を実行して下さい。

#include <stdio.h>

int main()
{
    int variable = 65;
    printf("variable: %c\n", (char)variable);
    return 0;
}

結果は、どうでしょうか。 variable: A と表示されましたか?
つまり、 int 型の 65 というのは、char 型だと A になるのです。
以下のように意味を変えていると見た方いいかもしれません

【2進数から整数型】 0100 0001 → 65
【2進数から文字型】 0100 0001 → A

しっくり来なくても大丈夫です。ポインタとはあまり関係ありませんので。 ただ、知ってると面白いかなと思って書きました(面白くなかった? ごめんなさい……)。

おわりに

今回は以上です。 書き終わってから思いましたが、ポインタと関係あるのか微妙ですね。 ただ、2進数が分かっているといろいろ便利なので、消さずに残しておこうと思いました。 2進数の計算は、Widnows標準の電卓で設定をプログラマーに変えると計算できるので 正確に計算できる必要はないですが、2 進数の計算と 2 の乗数の 10 乗と 5 乗は覚えておくと便利です。

UE4 で http 通信を行う

UE4 C++

少し前に 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)を選択します。

f:id:pickles-ochazuke:20170213214210p:plain

すると、VisualStudio が立ち上がると思います。気長に全ファイルを読み込むのを待ちます。
読み込めました? では、ビルドしましょう。
とくに問題が起こらないとは思うので、次に進みます。

アクタの作成

UE4 のエディタで http を取得するアクタを作ります。
まず、コンテンツブラウザの新規追加を選び、新規 C++ファイル… を選択します。親クラスは、Actorを選択します。
ファイル名は何でもいいです。今回は、GetHttpActorとしました。あと、パブリック、プライベートは特に選択しませんでした。
クラスを作成をクリックして、リコンパイルが終わるのを待ちます。

ソースコードの編集

では、プロジェクトの中身をいじっていきます。

Build.cs

”プロジェクトファイル名”.Build.cs という名前のファイルが VisualStudio のソリューションエクスプローラーにあると思います。
今回、自分のプロジェクト名は、MyProject(つまりデフォルトの名前)にしたので、MyProject.Build.cs というファイルがあるはずです……ありました。

f:id:pickles-ochazuke:20170213220228p:plain

見つかりましたか? よく探してくださいね。ソリューションエクスプローラーの検索を利用するといいかもしれません。例えば、.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/ とします(ポート番号は人によって異なります)。すると以下のような画面が表示されます。

f:id:pickles-ochazuke:20170214230230p:plain

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 エディタのプレイをクリックしましょう。
以下の画像のように文字が表示されるはずです。

f:id:pickles-ochazuke:20170214231918p:plain

無事、http 通信をすることが出来ました。とても小さなことですが、これだけでもいろいろ幅が広がります。長くなりましたが、以上です。 お疲れさまでした。

おわりに

http 周りのソースコード調べないとなぁ……。
あと、分かりづらいところがあればコメントを下さい。

Amazon Prime Music の曲紹介

音楽

はじめに

Amazon Prime Music で聴ける曲で、気に入った曲を紹介していく記事。
別々の記事にすると面倒そうなので、計画としてはこの記事に追記していく形。 いつまでも聴けるとは限らないので、その点ご注意。 あと主にOSTです。自分、歌(日本語)は疲れるのであまり聴きません。

OST:オリジナルサウンドトラック

#1.GRAVITY DAZE/重力的眩暈:上層への帰還において、彼女の内宇宙に生じた摂動 OST

タイトル長い。これは、ずっと前から聴ける曲なので、今後も聴ける気がする。
SCE(現SIE)のゲーム。ゲームは癖があるけど、このOSTは本当に最高。Prime Music にはまったきっかけ。万有引力の発見GRAVITY DAZE/重力的眩暈は必聴。
あ、自分はこのゲーム好きです。2 はまだ終わってないけど(2017/03/04 現在)。 Prime で聴けるけどサントラ欲しい。

#2.仮面の勇者~心の迷宮RPGOST

また良曲を見つけてしまった。これだから Prime Music は止められない。
ゲーム自体はやったことないのだけど、Android アプリのゲームらしい。
聴いたらピンと来るかもしれないけど、作曲者は、景山将太(かげやま しょうた)さん。主にポケモンを作曲している人らしい。というのも自分は、スマブラの印象が強かった。
一部しか聴けないし、短いからループが鬱陶しいかもしれないけど、一度は聴いてみて。

仮面の勇者?心の迷宮RPG? オリジナルサウンドトラック

仮面の勇者?心の迷宮RPG? オリジナルサウンドトラック

本読み Optimized C++ 1章

C++ 読書

Optimized C++ 1章

読んだ記録を取るためと、内容を整理するために文章にしていくプロジェクト。
飽きないように気をつける。で、Optimized C++ を購入して、とりあえず1章読み終わりました。
オライリー本は、内容が濃いから1ページ読むのに時間がかかる……(1時間半かかった)

1章は、本全体の概要みたいなもので流し読みで良いのだけど、
自分は最適化を意識したことがなかったので、じっくり読んでました。

この本について

この本は、C++ の最適化について書かれているので、 一部別の言語にも利用できるテクニックがあるかもしれないが、 別の言語に向けて書かれたものではない。
また、特定のプロセッサで利用できる命令などを使った最適化はしない。
これは、今の時代アプリは様々なプラットフォーム(主にプロセッサ)で動作するから。
OS も同様。この本は、C++ で何ができるかについて書かれている。

特定の技法(テクニック)を教えるものではない。
どうやって最適化をしていくかを学んでいく本。
考え方に近いかもしれない。また、コーディングプロセスの最適化も扱う。
最初にとりあえず実装するのではなく、最初から高速な処理を書けるようにする。

この本を読めば、以下の方法でコードの性能を改善することができる

  • より良いコンパイラを使い、最適化をオンにする
  • 最適なアルゴリズムを使う
  • より良いライブラリを使い、ライブラリをよりうまく使う
  • メモリ割り当てを減らす
  • コピーを減らす
  • 計算を取り除く
  • 愛的なデータ構造を使う
  • 並行性を増やす
  • メモリ管理を最適化する

1.1 最適化はソフトウェア開発の一部

速度、スループット、メモリ使用、消費電力の改善は、コーディングと同じほど重要。
低性能なアプリは、バグと同じ。

直感で最適化をすることはできない。
実際に計測し、その結果を見て最適化ができたかどうかを判断する。
直感ではなく実験によって最適化を行う。

1.3 最適化しても大丈夫

「単純」で非効率なコードをなぜ書かないのか尋ねられたら、「遅くて無駄なコードを書く時間と同じ時間で効率的なコードが書けるからだ。どうしてわざわざ非効率なコードを書くことを選択するの?」と答えればよい。

良くないのは、何が問題なのか分かっていないのに最適化をすること。
アセンブラで組み直せば速くなるとは限らないし、C++ より C の方が速いとは決まっていない。

大事なのは、何が原因になっているかを見つけること。その原因だけ対処すれば性能は向上する。

アルゴリズムを選択するときは、実験によって示すこと。噂や憶測でそのアルゴリズムを候補から消してしまってはいけない。
プロセッサの性能が高くなるから最適化をしなくていいというのは、嘘。最近のプロセッサの速度は、あまり向上していないし、場合によっては落ちている(個別コアで見た場合)。
特にモバイルプラットフォームだと速度だけでなく、発熱、バッテリーの消費量なども意識する必要がある。そもそもユーザが常に最新のプラットフォームを使うとは限らない。

1.4こちらにナノ秒、あちらにナノ秒

ハードウェアが高性能でも、その上で動く、ソフトウェアが使える資源は極一部。
モバイルやサーバでは、資源に制約がある。

1.5 最適化 C++ コード戦略のまとめ

最適化のホットスポットには、「いつもの容疑者」がいる。
関数呼び出し、メモリ割り当て、ループなど。
もちろんこれだけではないので、この本は、そういった隠れた箇所を見つけやすくする。

1.5.1 より良いコンパイラを使う、コンパイラをよりうまく使う

どのC++ コンパイラを使うべきかについての最も重要なアドバイスは、「C++11 適合コンパイラを使う」ということ

C++11 は、ムーブセマンティクスを実装している(6.6 ムーブセマンティクスの実装)

コンパイラによって最適化の方法は異なる。なので、コンパイラによっては性能が向上することがある。
コンパイラの最適化は、デフォルトでは OFF になっている。これを ON にするだけで解決するときもある。
ただし、デバッグ時は最適化は OFF にする。その方が、処理を追いやすい。

コンパイラの性能は、Intel C++ > Visual C++GNU C++ と言われている。
もちろん必ずこうなるわけではないので、実際に試してみる必要はある。

1.5.2 より良いアルゴリズムを使う

選択を間違ったアルゴリズムを最適化しても性能向上はあまり望めない。
別のアルゴリズムに変えるだけで、性能が向上することがある。
これについては、5章「アルゴリズムを最適化する」で紹介。
5.5「最適化のパターン」では、性能改善に重要な技法について紹介。事前計算、遅延計算、キャッシュなど。
7章「ホットな文を最適化する」で、これらの技法の例を示す。

1.5.3 より良いライブラリを使う

標準 C++ テンプレートとランタイムライブラリは、常に保守され、汎用で非常に頑健でなければいけない。つまり、標準のものが最適とは限らない。8章では、「優れたライブラリを使う」でこの問題を扱う。
C++ 標準ライブラリをマスターすることは、最適化開発者の必須スキル。

  • 選択や整列のアルゴリズム(9章)
  • コンテナクラスを使った最適イディオム(10章)
  • I/O(11章)
  • 平衡性(12章)
  • メモリ管理(13章)

なども扱う。
優れた関数ライブラリAPI は、ユーザに不必要な基本関数を呼ばせない。
ライブラリは、呼び出しコストに見合う最高の効率をユーザのプログラムにもたらすべき。
関数呼び出しのコストについては、7.2.1 で扱う。

1.5.4 メモリ割り当てとコピーを減らす。

文字列の最適化は、4章で扱う。
6章では、動的メモリ割り当てのコストを減らすことを論じる。
コピーを減らすことは、コードの速度向上に明らかに役立つ。
コピーに関するホットスポットは、コンストラクタ、代入演算子、入出力がある。

1.5.5 計算を取り除く

7章と3章を参照

1.5.6 より良いデータ構造を使う

10章、9章を参照。

1.5.7 並行性を高める

12章を参照。

1.5.8 メモリ管理を最適化する

13章を参照。

おわり

後半手抜きだけど、1章はこんな感じ。以上。
1年かけて読み進めていく予定。

Microsoft の CI ツールが多くて思考停止したので、整理してみる

勉強

【経緯】

唐突にCIツールを使ってみようと思い、Jenkins を自宅サーバ(久々に起動)に入れてみるも、家で作っているのはVisual C++ なので意味ないのでは? と気づき、調べているとMicrosoft のCI ツールを発見。TFS、VSTS、VSO……何がどう違うのか。

【CIとは】

Ceizokuteki Integration のこと……ではなく、Continuous Integration のこと。つまり継続的統合。Cは、コンテニューだと思っておけば覚えやすいかも。まだ利用したことないので理解は浅いけど、変更した内容をすぐに反映、ビルド、テストをすることでバグを早期発見し、品質を高める方法。

で、今回はそのCI環境を作るためのツールを調べたところ、Microsoft の CI ツールが複数あって、混乱したので調べた。

今回紹介するのは、以下

上から時代が古い順に並べたつもり。

簡単に説明すると、初めに Microsoft 製 CI ツールが出たのが、TFS。CI のための基本的な機能(ビルド、テスト、リリースなど)を提供してくれる。ただし、TFS を動かすためのサーバは自分たちで用意する必要がある。

次に VSO 。簡単に言うと Visual Studio のオンライン版。さらに機能が追加され、TFS のような機能も備えている。要は VS + TFS かも。

VSTS。これが今一番新しい。TFS のような機能をクラウドサービスとして提供している。サーバを持つ必要がないので、CI に集中することが出来る。

で、VSTS を動かしているのが Azure。Azure が動かしているので(?)簡単に Azure と連携をすることが出来る。Web 系開発のときに Azure との相性が良い。

気にする必要があるのは、TFS と VSTS。Azure は人による。

TFS より VSTS の方が便利そうだけど、TFS はローカルで構築することが出来るので、全く利用価値がないわけではない。

全体としては以上。一つ一つ紹介していく

Team Foundation Server(TFS)】

大きな機能として、バージョン管理、アジャイル開発をするときに便利なツールやビルド、パッケージ、テスト、リリースを自動で行うなどの機能を備えている。

ローカルで解決したいときは、こいつをインストールする。

Visual Studio Online(VSO)】

特に重要ではないので簡単に説明する。

VS + TFS のオンライン版。つまりクラウドサービス。現在は、Visual Studio Team Services(あとで紹介)という名前に変わっている。なので、説明は VSTS に譲る。

Visual Studio Team Services】

一番名前が長い。CIのための基本的な機能はもちろん。サーバの構築が不要で、サインアップするだけで利用することが出来る。

このサービスは、Azure の上で動いているので、Azure のサービスの一つだと思って良さそう。個人で使うだけなら無料で利用可能(利用人数によるが)。Azure との相性が良いので、Azure を使った、Web アプリを開発したり、Xamarin を使ったスマフォアプリ開発などに便利(どちらも作ったことないので見当違いなこと書いてるかも……)。

CI 機能使わないから関係ないと思っている人にも知っていて欲しいのが(ここまで読んでいるか怪しいけど)、バージョン管理。

例えば、バージョン管理のためのサーバが欲しい。けど、Github は無料だと公開しないといけない恥ずかしいって人は、VSTS を使うと良いかもしれない(あまりそういう籠もる姿勢はおすすめしないけど)。なんとバージョン管理をプライベートで利用できる。バージョン管理のツールは Git に近い感じ。Git も使うことが出来る。

Visual Studio 2017 では、VSTS を利用するための機能が強化されるそうなので、VSTS を検討する余地はあるかと。 

【参考資料】

Team Foundation Server - Visual Studio

www.visualstudio.com

blogs.msdn.microsoft.com

Visual Studio Team Services - Visual Studio

  • Azure

docs.microsoft.com

www.atmarkit.co.jp