最近読んだ本・漫画を振り返る 2019年10月編
読書メモとして、最近読んだ技術書、一般書、漫画で面白かった本をブログに残していこうと思う。一応2~3ヶ月に一度は書くつもりでいる。
技術書
通信・ネットワーク周り
マスタリングTCP/IP 入門編 第5版
- 作者: 竹下隆史,村山公保,荒井透,苅田幸雄
- 出版社/メーカー: オーム社
- 発売日: 2012/02/25
- メディア: 単行本(ソフトカバー)
- 購入: 4人 クリック: 34回
- この商品を含むブログ (37件) を見る
最早私が説明するまでもない、コンピュータ通信技術入門の大名著。ある論文の紹介をする際、何度も読み返し、その度にわかりやすい説明に感銘を受けた。
アプリケーション層しか触らないような人でも読むべき。というかコンピュータに関わる技術者はみんな読むべき。
改訂三版 802.11高速無線LAN教科書
改訂三版 802.11高速無線LAN教科書 (インプレス標準教科書シリーズ)
- 作者: 守倉正博,久保田周治
- 出版社/メーカー: インプレスR&D(インプレス)
- 発売日: 2008/03/27
- メディア: オンデマンド (ペーパーバック)
- 購入: 1人 クリック: 2回
- この商品を含むブログを見る
研究の参考に教授に勧められた本。発売が2008年ということで802.11nまでの情報しか乗ってないが、802.11x系の無線通信フレームのフォーマットについて、くどいほど詳しく書いてある。TCP/IPを一定程度理解した人間が、Wifi周りの勉強をする時はまず最初に読んで、間違いないと思う。早く.11ac対応版出て。
Linuxネットワークプログラミング
- 作者: あきみち
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2010/03/03
- メディア: 大型本
- 購入: 1人 クリック: 75回
- この商品を含むブログ (10件) を見る
Linuxネットワークプログラミングバイブル
- 作者: 小俣光之,種田元樹
- 出版社/メーカー: 秀和システム
- 発売日: 2014/10/07
- メディア: Kindle版
- この商品を含むブログ (1件) を見る
IPv6に対応した貴重なネットワークプログラミングの入門本。これがなかったら研究室でコードなにも書けないニートになるところだった。
ゲームプログラミング・3DCG関連
コンピュータグラフィックス [改訂新版]
- 出版社/メーカー: 画像情報教育振興協会
- 発売日: 2016/09/20
- メディア: 単行本
- この商品を含むブログを見る
Effective Modern C++
Effective Modern C++ ―C++11/14プログラムを進化させる42項目
- 作者: Scott Meyers,千住治郎
- 出版社/メーカー: オライリージャパン
- 発売日: 2015/09/18
- メディア: 大型本
- この商品を含むブログ (7件) を見る
C++ポケットリファレンス
[改訂第3版]C++ポケットリファレンス (POCKET REFERENCE)
- 作者: 高橋晶,安藤敏彦,一戸優介,楠田真矢,湯朝剛介
- 出版社/メーカー: 技術評論社
- 発売日: 2018/02/15
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
一般書
岩田さん 岩田聡はこんなことを話していた。
- 作者: ほぼ日刊イトイ新聞,100%ORANGE
- 出版社/メーカー: 株式会社ほぼ日
- 発売日: 2019/07/30
- メディア: 新書
- この商品を含むブログを見る
(Linux) UDPを使って一定時間おきに文字列を送信するプログラム
研究室でUDPを使った無線通信の受信側が受信待ち状態にない時のパケットキャプチャをする必要があったので書いた.
劣化iperfにすぎないとか言ってはいけない.
#include <arpa/inet.h> #include <netinet/in.h> #include <stdlib.h> #include <sys/socket.h> #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <unistd.h> enum { DEST_PORT = 12345 }; void rand_text(int length, char* result) { int i, rnd_int; const char char_set[] = "01234567890abcdefghijklmnopqrstuvwkyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; for (i = 0; i < length; i++) { result[i] = char_set[rand() % strlen(char_set)]; } result[length] = 0; } // ./main 192.168.20.2 7360(1パケットあたりのUDPデータ長[Byte]) 1(何秒間隔で送るか) count(合計何回送るか) int main(int argc, char* argv[]) { if (argc < 5) { printf("command line arguments is invalid!\n"); return 1; } const char* dest_addr = argv[1]; const int udp_data_len = atoi(argv[2]); const int interval_sec = atoi(argv[3]); const int count_max = atoi(argv[4]); printf("Send random data(%dByte) %dtimes to %s through UDP to every %d sec\n", udp_data_len, count_max, dest_addr, interval_sec); char* str; str = (char*)malloc(sizeof(char) * udp_data_len); srand(time(NULL)); rand_text(udp_data_len, str); printf("create string strlen(%ld)\n", strlen(str)); int sock = socket(AF_INET, SOCK_DGRAM, 0); struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(DEST_PORT); addr.sin_addr.s_addr = inet_addr(dest_addr); int count = 0; while (count < count_max) { printf("send %ldByte\n", strlen(str)); sendto(sock, str, strlen(str), 0, (struct sockaddr*)&addr, sizeof(addr)); printf("----------\n"); sleep(interval_sec); count++; } free(str); return 0; }
30分程度で書いた使い捨てのプログラム故,エラー処理が一切書いてないのに注意.
std::bindではデフォルト引数を省略できない
std::bindを使っていたらある問題に遭遇した。
void func(int a){ std::cout << a * 10 << std::endl; } int main(){ using namespace std::placeholders; auto fuction = std::bind(func, _1); function(2); }
std::bind
を使ってライブラリで用意されている関数を束縛し別のところで呼び出す、といったことをしたかったのだが、これが何故かコンパイルが通らなかった。(実際は、クラスのメンバ関数をbindした。簡単のためそのコードはここに示す )
なぜだろうか……といろいろ調べて回ったところ、とても単純な話だった。
void func(int a, int b = 10){ std::cout << a * b << std::endl; } int main(){ using namespace std::placeholders; auto fuction = std::bind(func, _1); function(2); }
引数1つで呼び出すものと思っていたfunc()
関数が、実際は第2引数にintを取る関数で、それにデフォルト引数が設定されていた。じゃあどうやってこの関数を束縛すればいいかというと、bind時、デフォルト引数も明示的に渡せばよい。
// Error! // auto function = std::bind(func, _1); // OK! auto function = std::bind(func, _1, 10); // call function(2);
bindは使うべきではないという話
ここまでbind
を使って関数を束縛してきたが、調べてみると、bindはパフォーマンス上に問題があるらしい。
じゃあ代わりに何を使うのかっていうと、みんな大好きラムダ式である。
// Error! // auto function = std::bind(func, _1); // OK! (low performance) auto function = std::bind(func, _1, 10) // OK! (high performance) auto function = [=](int _1){ func(_1); }; // call function(2);
Compiler Explorer でbind
とラムダ式
を比較してみると一目瞭然でパフォーマンスにかなり影響することがわかる。
まとめ
bindなんか使わずラムダを使おう。
VSCodeでAsciidocを書く時相対パス入力補完を働かせる
当ブログで何度か紹介しているAsciidocだが,仕様書を書いたり,レポートを書いたりするのに非常に重宝している.
ただ,画像挿入時などで,相対パスの記述をする時に,Path InteliSenceによる入力補完が効かないことがとにかく不便だった.
import {} from './include/hogehoge' // 引用符で囲む時は補完が効く image::./img/sample.png // 引用符で囲んでいないので補完が効かない
この度この問題を解決出来たのでメモ.
Path Autocompleteによるパス入力補完
まず,Path Intelisenceを入れている場合はアンインストールし,代わりに,Path Autocompleteを導入する.
ただ,Path Autocompleteのデフォルト設定のままでは,目的の入力補完が効かない.
- Path Autocompleteのデフォルト設定
import {} from './include/hogehoge' // 引用符で囲む時は補完が効く image::./img/sample.png // 引用符で囲んでいないので補完が効かない
Path Autocompleteの設定の内, path-autocomplete.triggerOutsideStrings
をtrue
にすると,引用符で囲まなくても入力補完が効くようになる.
しかしながら,これでも,目的の入力補完が効かない.
- Trigger Outside Strings On
import {} from './include/hogehoge' // 引用符で囲む時は補完が効く ./img/sample.png // 引用符で囲まなくても補完が効く image::./img/sample.png // ':' と './'の区切りを認識出来ないので補完が効かない.
path-autocomplete.pathSeparators
は,文と ./
の区切りを定義している.ここに,:
を加えることで, image::./img/sample.png
と入力する時も,相対パスの補完が効くようになる.
まとめ
- Path Autocompleteを導入
- path-autocomplete.triggerOutisideStringsをtrueに設定
- path-autocomplete.pathSeparatorsに
:
を追加 - おわり!
プログラミングに関する調べ物や最新技術のキャッチアップ方法
※注 ポエム要素が高い記事です
最近は研究室で忙しく、ブログに公開できるようなネタになるようなことをやれないでいる。 しかし、月イチ更新は守りたい → じゃあプログラミングを始めた頃の自分が知りたかった情報を書こう → プログラマーってどうやって最新技術を追いかけて、わからなかったことを調べているんだ、と当時考えていたことを思い出す
というわけで、今の自分が実践している、プログラミングに関する調べ方、最新技術のキャッチアップ方法をつらづらと書いていく。
Google検索
まずはここから。どんなときも、わからないことがあったらGoogleに聞けば大体解決する。しかしながら、ここ最近のプログラミング関連のワードの、Google日本語検索の上位に出てくる記事は くだらないゴミ記事 正しい情報が書かれていないモノが増えてしまい、求めている、正確な情報には簡単にたどり着けなくなっている(特にPythonとか酷い)。あまりにも酷いサイトは、ブラウザの拡張機能で検索結果に表示されなくするのが吉。(FireFoxユーザの私はPersonal BlockList を使っている)
初学者の内は日本語情報でも十分だが、そのうち、日本語情報では不足するようになる。そういったときは、公式リファレンスや、Stack Overflow、Google英語検索を利用している。英語が読めなくても近年の機械翻訳は相当な精度なので、十分読めている。
書籍
信頼と安心の情報源。古い本だと、最新の環境で使えないことがままあるが、それでも、基礎を抑えるには最良の手。なにか新しい言語、ライブラリに挑戦するときは、まず、書籍を当たるようにしている。
また、特に買う予定の本もないのに本屋に行く事も続けている。何か行き詰まっていたり、求めている機能を提供してくれるソフトが見当たらなかったりした時、本屋に行くと答えがあったりする。そして買う予定のなかった本を買って財布が薄くなる。
はてなブックマーク
Qiitaやら、ITMediaやら、engadgetやら、各サイトそれぞれ見にいくってのも一つの手ではあるが、毎日全部見るというのは、現実的には難しい。私は、代わりにはてブの テクノロジーカテゴリのトレンド を一通り見ている。 トレンドに上がっている中で、気になる情報があればそのサイトに飛んでみるし、タイトルだけ見ておくだけでも、最新トレンドを知(った気にな)ることができる。
その分野の第一人者とも言えるような人をフォローし、 TweetDeck
でその人の全ツイートを追っかける、みたいなストーカー的ムーブができる。真似しないほうがいい。
最近、ハマっているのは、エラーに悩まされていたり、ソフトの使い方がわからなかったときに、Google検索の前に、Twitter検索で調べるということ。「Python リスト」みたいなざっくりした検索ワードだと、なんの役にも立たないが、エラー番号等、詳細なキーワードで検索すると、Google検索するより早く解決することがある。
興味のある技術分野に関わる人々を沢山フォローすると、TLを眺めているだけで有益な情報が集まってくる。
デメリットはTwitterにハマりすぎて、作業が疎かになりがちなこと。(そしてこれが最近の悩みでもある)
まとめ
こういって調べ事をしていると、最初の内は何のことかわからないワードだらけだが、継続は力なり。いずれ理解できる日が来る。そして1理解すると10理解できない事が生まれ、またそれを調べる。プログラマーとはそうやって永遠に終わりのない調べ物をし続ける生き物なのだなぁとつくづく思う近頃。これからも続けていきたい。
Dungeon Template LibraryをUE4で利用してLandscapeを自在に操る
@wanotaitei さんが開発しているDungeon Template Library(以後DTL) がUE4で使えそうだったので使ってみた。
DTL(ランダム地形生成ライブラリ)とUE4で遊んでみる会 #UE4 #UE4Study pic.twitter.com/un9FMRTf1e
— ai (@ai_9684_dct) May 17, 2019
画像
UE4でDTLを使えるようにする
上記リンクからDTLをcloneしておく。
C++プロジェクトとしてUE4プロジェクトの Source/
以下に library/DTL
ディレクトリを作成。そこに、DTLライブラリの include
以下をコピーする。
UE4プロジェクトを開き直し、 (プロジェクト名)Build.cs
に以下を記述。
PublicIncludePaths.Add(ModuleDirectory + "/library/DTL/"); PrivateDependencyModuleNames.AddRange(new string[] { "Landscape", "LandscapeEditor" });
これで、DTLと、後に使うLandscape関連の関数が利用できるようになる。
Landscapeを操作する関数を実装する
BlueprintFunctionLibraryを継承したクラスを作成し、以下をコピペ。
- DTLLandscapeControlInEditor.h
#pragma once #include "CoreMinimal.h" #include "Kismet/BlueprintFunctionLibrary.h" #include "DTLLandscapeControlInEditor.generated.h" UCLASS() class DTLSAMPLEUE4_TPS_API UDTLLandscapeControlInEditor : public UBlueprintFunctionLibrary { GENERATED_BODY() UFUNCTION(BlueprintCallable, Category = DTL, meta = (HidePin = "worldContextObject_", DefaultToSelf = "worldContextObject_")) static bool perlinNoise(const UObject* worldContextObject_, float scale); };
- DTLLandscapeControlInEditor.cpp
#include "DTLLandscapeControlInEditor.h" #include "EngineUtils.h" #include "Landscape.h" #include "LandscapeInfo.h" #include "LandscapeEditor/Public/LandscapeEditorUtils.h" #include <DTL.hpp> bool UDTLLandscapeControlInEditor::perlinNoise(const UObject* worldContextObject_, float scale) { UWorld* world = worldContextObject_->GetWorld(); for (TActorIterator<ALandscape> actorItr(world); actorItr; ++actorItr) { ALandscape* landscape = *actorItr; if (landscape != nullptr) { // 2: ULandscapeInfoの初期化 ULandscapeInfo::RecreateLandscapeInfo(world, false); FIntRect rect = landscape->GetBoundingRect(); int32 w = rect.Width() + 1; int32 h = rect.Height() + 1; using shape_t = uint16; std::vector<std::vector<shape_t>> matrix(h, std::vector<shape_t>(w, 0)); constexpr double frequency = 6.0; constexpr uint8_t octaves{ 16 }; const uint32_t seed{ static_cast<uint32_t>( rand() ) }; const dtl::utility::PerlinNoise perlin(seed); double frequency_x{ w / frequency }; double frequency_y{ h / frequency }; for (std::size_t row{}; row < h; ++row) for (std::size_t col{}; col < w; ++col) matrix[row][col] = static_cast<shape_t>(50.0 * perlin.octaveNoise(octaves, col / frequency_x, row / frequency_y)); TArray<uint16> Data; Data.Init(0, w * h); for (auto x = 0; x < w; x++) { for (auto y = 0; y < h; y++) { Data[x * h + y] = static_cast<uint16>(FMath::FloorToInt(scale * matrix[y][x])); } } LandscapeEditorUtils::SetHeightmapData(landscape, Data); return true; } } return false; }
エディタ側からコンパイルし、通れば成功。
実装した関数を呼び出すActorを作成
Actorを継承したブループリントクラスを作成。画像のようなBPを組む。この際、EventPerlinNoise
は Call in Editor
フラグにチェックを、Scale
float変数は、Instance Editable
と Expose on Spawn
にチェックを入れる、
作成したActorを 適当にレベルに配置、続いて、Landscapeを作成し、機能別サンプル
から取ってきたLandscape Material
を適当に割り当てて上げれば完成。
まとめ
現在エディタ側からしかLandscapeを操作出来ないが、ランタイムでLandscapeを操作できると嬉しい。また、まだ試してないが、他のダンジョン生成関数との連携は簡単にできそう。
参考サイト
WSLのUbuntu18.04でmatplotlibを使えるようにするまで
WSLのUBuntu18.04はGUI表示が存在しないので、matplotlibを使ったグラフ描画ができない。だが、調べてみると、何とか描画できるようにできたので、メモしておく。
前準備
> sudo apt update && sudo apt upgrade > sudo apt install python3-pip
matplotlibの導入
pip3を使ってmatplotlibと、セットで使われがちなnumpyを導入しておく
> pip3 install numpy > pip3 install matplotlib
matplotlibを使った参考プログラム
vim等のエディタを使って、以下のコードを入力
> vim sampleGraph.py
import matplotlib.pyplot as plt import numpy as np x = np.linspace(0, 10, 100) y = np.random.randn(100) plt.plot(x, y) plt.show()
これを実行してみる。
> python3 sampleGraph.py
この時点で Tkinter
がないだのというエラーが出たら、以下のコマンドを実行
> sudo apt install python3-tk > sudo apt install tk-dev
ウィンドウに描画できるようにする
sourceForgeで、VcXsrvをDLする。
インストーラーでは特に追加設定の必要なし。指示通り勧めていけばよい。
インストールが終わったら、Windowキーを押し、XLaunchを実行する。
デフォルト設定のまま進め、完了を押す前にSave configuration
を押し、設定ファイルをわかりやすいところ、例えばデスクトップに保存しておく。
完了を押せば、XLaunchが起動する。
WSLに戻って、以下のコマンドを実行。
> sudo vim ~/.bashrc
最後の行に以下を追加して保存する。
export DISPLAY=:0.0
WSLを再起動(ウィンドウを閉じるか、exitすれば良い)すればこの設定が読み込まれて、設定が反映される。
この後pythonを実行すると
> python3 sampleGraph.py
こんな感じでウィンドウが表示されるようになる。