tag:crieit.net,2005:https://crieit.net/tags/C%2B%2B/feed 「C++」の記事 - Crieit Crieitでタグ「C++」に投稿された最近の記事 2023-04-10T00:50:27+09:00 https://crieit.net/tags/C%2B%2B/feed tag:crieit.net,2005:PublicArticle/18422 2023-04-09T21:54:23+09:00 2023-04-10T00:50:27+09:00 https://crieit.net/posts/OS-6432b57f27a42 【随時更新】「ゼロからのOS自作入門」の実践 <p><a target="_blank" rel="nofollow noopener" href="https://www.amazon.co.jp/dp/4839975868?&_encoding=UTF8&tag=nightbug-22&linkCode=ur2&linkId=14df8d2610c24373245d26ad5a25657d&camp=247&creative=1211">ゼロからのOS自作入門</a><br /> 第3刷を読みながら、基本的には内容通りにやっていき、詰まったところをメモしていく。<br /> 記事を分けずに追記を重ねていきます。</p> <h1 id="環境"><a href="#%E7%92%B0%E5%A2%83">環境</a></h1> <ul> <li>OS<br /> Windows11</li> <li>開発環境<br /> WSL2+ubuntu18.04にみんな大好きVSCodeからSSH接続する形で作業<br /> <a target="_blank" rel="nofollow noopener" href="https://github.com/uchan-nos/mikanos-build">https://github.com/uchan-nos/mikanos-build</a>の「ビルド環境の構築」に従い環境構築</li> </ul> <h1 id="1章"><a href="#1%E7%AB%A0">1章</a></h1> <h2 id="1.1"><a href="#1.1">1.1</a></h2> <h3 id="WSL2でokteta使えるよ"><a href="#WSL2%E3%81%A7okteta%E4%BD%BF%E3%81%88%E3%82%8B%E3%82%88">WSL2でokteta使えるよ</a></h3> <p>バイナリエディタoktetaのインストール。書籍ではWSLならWindowsのバイナリエディタを使った方が良いとあったが、現在のWSLはGUIアプリに対応しているため、oktetaがそのまま使える。<br /> リンク:<a target="_blank" rel="nofollow noopener" href="https://forest.watch.impress.co.jp/docs/news/1458044.html">Windows 10でもLinux GUIアプリが利用可能 ~Microsoft Store版が既定の「WSL」に</a></p> <h2 id="1.4"><a href="#1.4">1.4</a></h2> <h3 id="実行環境"><a href="#%E5%AE%9F%E8%A1%8C%E7%92%B0%E5%A2%83">実行環境</a></h3> <p>作成したEFIの実行環境は、書籍では以下の3通りが紹介されていた。<br /> ・USBメモリに入れて同じPCで起動(いちいち開発環境の中断になるため、非推奨)<br /> ・USBメモリに入れて別PCで起動<br /> ・エミュレータ(QEMU)での起動<br /> 自分はQEMUでの起動を選択したが、ubuntu版ではなくWindows版QEMUをインストールした。<br /> この場合ビルド・デプロイした一式をWindowsから起動する1手間が必要になるが、VcXsrvのインストール・常駐は不要になる。Windows版は性能に制限がありそうなので、今後限界が来たら諦めてubuntu版QEMUを使用する事にする。</p> <h3 id="バイナリ直打ち結局動かない"><a href="#%E3%83%90%E3%82%A4%E3%83%8A%E3%83%AA%E7%9B%B4%E6%89%93%E3%81%A1%E7%B5%90%E5%B1%80%E5%8B%95%E3%81%8B%E3%81%AA%E3%81%84">バイナリ直打ち結局動かない</a></h3> <p>書籍ではまずバイナリエディタで直接HalloeWorld実行ファイルを作成し、それを起動していたが、自分の環境ではどうやっても「Start PXE over IPv4」のエラーが出て正常に起動しなかった。まあ筆者と環境が違ったらその可能性もあるのでは?と、この項目をあきらめて、次に進んだ。</p> <h2 id="1.9"><a href="#1.9">1.9</a></h2> <p>C++で1.4章と同じ内容のソースコードを作成・ビルドしたものを起動したら、こちらは正常起動した。なので1.4章がうまくいかなくても次に進んでしまって問題はないと思う。<br /> そう考えるといろんな環境に対応してるWindowsってすごいなって思った。</p> <h1 id="2章"><a href="#2%E7%AB%A0">2章</a></h1> <h2 id="2.2"><a href="#2.2">2.2</a></h2> <h5 id="git不慣れマン"><a href="#git%E4%B8%8D%E6%85%A3%E3%82%8C%E3%83%9E%E3%83%B3">git不慣れマン</a></h5> <p>書籍に書いてあるcheckoutじゃなくてcloneした。</p> <pre><code class="bash">git clone -b osbook_day02a https://github.com/uchan-nos/mikanos.git </code></pre> <h5 id="EDKⅡビルドでの生成ファイルの場所"><a href="#EDK%E2%85%A1%E3%83%93%E3%83%AB%E3%83%89%E3%81%A7%E3%81%AE%E7%94%9F%E6%88%90%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E5%A0%B4%E6%89%80">EDKⅡビルドでの生成ファイルの場所</a></h5> <p>自分は以下になっていました。<br /> <code>/home/common/edk2/Build/MikanLoaderX64/DEBUG_CLANG38/X64/MikanLoaderPkg/Loader/DEBUG/Loader.efi</code></p> <h2 id="2.5"><a href="#2.5">2.5</a></h2> <h5 id="すすめかた"><a href="#%E3%81%99%E3%81%99%E3%82%81%E3%81%8B%E3%81%9F">すすめかた</a></h5> <p>checkoutして本読んでビルドするだけでは勉強にならなそう、でも写経は大変そうだったので、<br /> 1. 2.2章でcloneしたソースにgithubの該当タブのソース差分を直接コピペして育てていきながら<br /> 2. 本を読んでソース上にコメントで読解内容を書き込み<br /> でやっていく事にする。<br /> <a href="https://crieit.now.sh/upload_images/2b30e9729b2b45bf6fe4eb8e39ef58ee6432de70e084b.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/2b30e9729b2b45bf6fe4eb8e39ef58ee6432de70e084b.png?mw=700" alt="image.png" /></a></p> uskz tag:crieit.net,2005:PublicArticle/18171 2022-04-18T17:53:40+09:00 2022-04-18T17:53:40+09:00 https://crieit.net/posts/Win32API-Drag-Drop Win32APIでDrag&Dropしたファイルをある場所にコピーする方法 <p><strong>Win32APIでDrag&Dropしたファイルをある場所にコピーする方法</strong></p> <p>1.宣言</p> <pre><code class="CPP">#include "Shlwapi.h" // Shlwapi.hの関数を使用するために下記の追加が必要 #pragma comment (lib, "Shlwapi.lib") </code></pre> <p>2.実処理</p> <pre><code class="CPP"> UINT n; UINT i; UINT ret; TCHAR pszBuff[MAX_PATH * 10] = {}; TCHAR pszNewFile[MAX_PATH * 10] = { _T("\\\\wsl$\\Arch\\mnt\\wsl\\share")}; n = DragQueryFileA((HDROP)wParam, -1, NULL, 0); for (i = 0; i < n; i++) { ret = DragQueryFile((HDROP)wParam, i, pszBuff, MAX_PATH * 10); if (ret == -1) continue; LPWSTR fileName = PathFindFileNameW(pszBuff); wsprintf(pszNewFile, L"%s\\%s", pszNewFile, fileName); // 第3引数がFalseなので、コピー先に同名ファイルがあった場合は上書保存 // TRUEにした場合は、失敗してエラーになる CopyFile(pszBuff, pszNewFile, FALSE); } </code></pre> <p>Drag&Dropしたファイルを、WSL2のマウントフォルダに格納するようにした。<br /> Shlwapi.hの関数は「PathFindFileNameW」。<br /> ヘッダをincludeしただけだと、「未定義の関数」としてビルド時にエラーになる。<br /> 「#pragma comment (lib, "Shlwapi.lib")」を追記すると、Shlwapi.libをプロジェクトに参照追加しなくても動作するようになる。<br /> 理由がわかっていないので調査したい。</p> <p>「PathFindFileNameW(pszBuff)」を実行して取得できるのは「xxxx.txt」のようなファイル名部分となる。<br /> 「PathFindFileNameW」を使用しているのは、TCHARを使用しているから。<br /> CHARを使用する場合はたぶん「PathFindFileNameA」を使用するんだと思う。</p> <p>「wsprintf(pszNewFile, L"%s\%s", pszNewFile, fileName);」で、変数pszNewFileにコピー先のpathと取得したファイル名を連結している。</p> ao-iro tag:crieit.net,2005:PublicArticle/16675 2021-02-07T20:36:55+09:00 2021-03-05T17:28:58+09:00 https://crieit.net/posts/C-Vector [C++] Vector配列でクラスを扱う時にクラスメンバーにリファレンスが含まれていると面倒 <p>オブジェクトをVector配列に積んだり消したりするソースでも書くか・・・</p> <pre><code>#include <vector> #include <algorithm> using namespace std; class A { public: A() = delete; A(int item) : m_item(item) {} private: int &m_item; }; class MainProc { public: void AddVector(A obj) { m_vecA.emplace_back(obj); } void DelVector(A srcobj) { if (m_vecA.size()) { auto it = remove_if(m_vecA.begin(), m_vecA.end(), [&](A &dstobj) { return (dstobj.m_item == srcobj.m_item); }); m_vecA.erase(it, m_vecA.end()); } } private: vector<A> m_vecA; }; int main() { MainProc MP; int i1 = 1, i2 = 2; A obj1(i1), obj2(i2); MP.AddVector(obj1); MP.AddVector(obj2); MP.DelVector(obj1); } </code></pre> <p>ビルドしたら難しそうなエラーが出ました。</p> <pre><code>main.cpp:24:122: required from here /usr/include/c++/7/bits/stl_algo.h:871:16: error: use of deleted function ‘A& A::operator=(A&&)’ *__result = _GLIBCXX_MOVE(*__first); ^ main.cpp:5:7: note: ‘A& A::operator=(A&&)’ is implicitly deleted because the default definition would be ill-formed: class A : </code></pre> <p>想像なのであまりあてにしないで欲しいんですが、多分↓のような感じ?</p> <p>・remove_ifとかeraseのところでclassAの代入(operator=)をしたいよ<br />  →でもoperator=はこちらでdeleteしときましたよ<br />   →なんでかというと代入できるならしたいけどclassAのメンバーにリファレンスがいて無理だからだよ</p> <p>面倒なのでclassAのm_itemをポインタ型にして解決しました。</p> uskz tag:crieit.net,2005:PublicArticle/15938 2020-06-10T08:58:14+09:00 2020-06-10T08:59:25+09:00 https://crieit.net/posts/Unreal-Engine-5ee0221605a10 Unreal Engineで実行中にテクスチャを更新するサンプル <p>Unreal Engineで実行時にテクスチャの色を変更できたら便利かなと思って試したもの。できたはできたが思ったようにうまくはいかなかった。ためしに白色を他の色に変えようと思ったのだが、ムラができてしまった。元の画像がそうなのか、UEに取り込まれてミップマップ化された時にそうなったのかはわからない。検証するかもしれないししないかもしれないのでとりあえずメモだけ。</p> <pre><code class="cpp"> UPrimitiveComponent* Primitive = Cast<UPrimitiveComponent>(GetComponentByClass(UPrimitiveComponent::StaticClass())); UMaterialInstanceDynamic* Material = Primitive->CreateAndSetMaterialInstanceDynamicFromMaterial( 0, Cast<UMaterial>(StaticLoadObject(UMaterial::StaticClass(), nullptr, TEXT("/Game/Materials/MyMaterial"))) ); UTexture2D* Texture = Cast<UTexture2D>(StaticLoadObject( UTexture2D::StaticClass(), nullptr, TEXT("/Game/Model/train/Textures/MyTexture") )); Texture->CompressionSettings = TextureCompressionSettings::TC_VectorDisplacementmap; Texture->MipGenSettings = TextureMipGenSettings::TMGS_NoMipmaps; Texture->SRGB = false; Texture->UpdateResource(); struct RGBA { uint8 R, G, B, A; }; RGBA* Data = (RGBA*)Texture->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_WRITE); int DataSize = Texture->PlatformData->Mips[0].SizeX * Texture->PlatformData->Mips[0].SizeY; for (int Index = 0; Index < DataSize; Index++) { RGBA* Color = Data + Index * sizeof(RGBA); // UE_LOG(LogTemp, Log, TEXT("RGBA %d %d %d"), Color->R, Color->G, Color->B); if (Color->R > 200 && Color->G > 200 && Color->B > 200) { Color->G = 0; } } Texture->PlatformData->Mips[0].BulkData.Unlock(); Texture->UpdateResource(); Material->SetTextureParameterValue(TEXT("BaseColor Map"), Texture); </code></pre> <p>このActorを画面上に配置してモデルのコンポーネントを追加して動かす。しかしそれにしても失敗するとすぐエディタが落ちる……。</p> <p>詳しく調べてないけどそのマテリアル自体が変わってしまって同時に複数の色にはできない場合、そうしたい人は別のやり方が必要なのかもしれない。</p> <p>下記を参考にした。</p> <p><a target="_blank" rel="nofollow noopener" href="https://usagi.hatenablog.jp/entry/2017/07/26/115603">UE4/C++: メッシュのマテリアルやテクスチャーをC++コードで制御する方法 - C++ ときどき ごはん、わりとてぃーぶれいく☆</a></p> だら@Crieit開発者 tag:crieit.net,2005:PublicArticle/15921 2020-06-05T22:12:19+09:00 2020-06-05T22:12:19+09:00 https://crieit.net/posts/Unreal-Engine-5eda44b3abbb2 Unreal Engineで画面のサイズとタップ座標を取得する <p>Unreal EngineでC++を使って画面のサイズを取得する方法。</p> <pre><code class="cpp">#include "Kismet/GameplayStatics.h" void AMyPawn::GetTest() { AMyPlayerController* PlayerController = Cast<AMyPlayerController>( UGameplayStatics::GetPlayerController(GetWorld(), 0) ); float x, y; PlayerController->GetMousePosition(x, y); int width, height; PlayerController->GetViewportSize(width, height); } </code></pre> <p>他にも解像度取得もあったりしてそっちの機能はサイズが異なる(やり方はメモってなかったので忘れてしまった)。今回はちゃんとゲーム画面のサイズが欲しかったのでGetViewportSizeを使った。</p> <p>正しいのかどうかよく分かってない&まだちょっと実機では試してないのでとりあえずメモ。</p> だら@Crieit開発者 tag:crieit.net,2005:PublicArticle/15872 2020-04-27T12:09:32+09:00 2020-04-27T12:22:31+09:00 https://crieit.net/posts/cpp-overflow-int-abc162-d C++でint型同士の演算結果をlong longで受け取っても、オーバーフローで正しい値にならない場合がある - ABC 162 D - RGB Triplets <p>緊急事態宣言に伴う自粛期間中なので、昨日は家にこもってAtCoder(競技プログラミング)の過去問を練習していました。</p> <p>昨日は「<a target="_blank" rel="nofollow noopener" href="https://atcoder.jp/contests/abc162/tasks/abc162_d">ABC 162 D - RGB Triplets</a>」を解いていたのですが、なぜかtestcase_17とtestcase_18だけACにならず、長時間悩みました。</p> <p>結論から言ってしまうと<strong>int型同士の演算によるオーバーフロー</strong>が原因だったのですが、実際のプログラム例を掲載します。</p> <h2 id="オーバーフローで結果が異なる例"><a href="#%E3%82%AA%E3%83%BC%E3%83%90%E3%83%BC%E3%83%95%E3%83%AD%E3%83%BC%E3%81%A7%E7%B5%90%E6%9E%9C%E3%81%8C%E7%95%B0%E3%81%AA%E3%82%8B%E4%BE%8B">オーバーフローで結果が異なる例</a></h2> <p>次のC++プログラムにある「R1,R2」「G1,G2」「B1,B2」の各変数は、それぞれ1333を代入しています。<br /> 1333は小さな数で、int型の範囲内です。</p> <p>ただし計算結果は大きな値となるため、long longで受け取ることにしました。</p> <pre><code class="cpp">#include <bits/stdc++.h> using namespace std; int main() { int R1 = 1333; int G1 = 1333; int B1 = 1333; long long res1 = R1 * G1 * B1; cout << res1 << endl; // -1926374259 long long R2 = 1333; long long G2 = 1333; long long B2 = 1333; long long res2 = R2 * G2 * B2; cout << res2 << endl; // 2368593037 } </code></pre> <p>見てわかるように、計算結果をlong longで受け取ったとしても、1333をint型にしたパターンでは結果が正しくなりません。</p> <h2 id="ハードコードで書き直してみる"><a href="#%E3%83%8F%E3%83%BC%E3%83%89%E3%82%B3%E3%83%BC%E3%83%89%E3%81%A7%E6%9B%B8%E3%81%8D%E7%9B%B4%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B">ハードコードで書き直してみる</a></h2> <p>変数に代入するパターンではオーバーフローが起きていたため、次にハードコードで書き直してみました。</p> <pre><code class="cpp">#include <bits/stdc++.h> using namespace std; int main() { // ハードコードのint long long res1 = 1333 * 1333 * 1333; cout << res1 << endl; // -1926374259 // ハードコードのlong long long long res2 = 1333LL * 1333LL * 1333LL; cout << res2 << endl; // 2368593037 } </code></pre> <p>計算結果は相変わらずですが、私の環境(GCC 9.2.0)では次の警告が発生しました。<br /> これにより、オーバーフローが発生していることがわかります。</p> <pre><code class="sh">$ g++-9 test.cpp test.cpp: In function 'int main()': test.cpp:9:34: warning: integer overflow in expression of type 'int' results in '-1926374259' [-Woverflow] 9 | long long res1 = 1333 * 1333 * 1333; | ~~~~~~~~~~<del>^</del>~~~ </code></pre> <h2 id="同じ型同士の演算と、異なる型による演算の違い"><a href="#%E5%90%8C%E3%81%98%E5%9E%8B%E5%90%8C%E5%A3%AB%E3%81%AE%E6%BC%94%E7%AE%97%E3%81%A8%E3%80%81%E7%95%B0%E3%81%AA%E3%82%8B%E5%9E%8B%E3%81%AB%E3%82%88%E3%82%8B%E6%BC%94%E7%AE%97%E3%81%AE%E9%81%95%E3%81%84">同じ型同士の演算と、異なる型による演算の違い</a></h2> <p>発生した警告の内容を見るに、int型同士の演算結果はintになるため、オーバーフローが発生したと推測できます。<br /> <strong>左辺で計算結果をlong longで受け取ったとしても、右辺の演算の時点でダメだったようです。</strong></p> <p>そこで右辺にlong longを組み合わせてみたところ、想定した値が返却されるようになりました。</p> <pre><code class="cpp">#include <bits/stdc++.h> using namespace std; int main() { // ハードコードのint long long res1 = 1333 * 1333 * 1333; cout << res1 << endl; // -1926374259 // ハードコードのlong long long long res2 = 1333LL * 1333LL * 1333LL; cout << res2 << endl; // 2368593037 // intとlong longを組み合わせた例 long long res3 = 1333 * 1333 * 1333LL; cout << res3 << endl; // 2368593037 } </code></pre> <h2 id="さいごに"><a href="#%E3%81%95%E3%81%84%E3%81%94%E3%81%AB">さいごに</a></h2> <p>1333のような小さな値であれば、単にint型へ保存すれば十分だと思っていました。</p> <p>しかし演算に用いるケースでは、演算結果がとり得る値の範囲や、演算結果の型も考慮したプログラミングが必要であると言えそうです。</p> <p>C++は競プロのために入門コンテンツを使って速習したくらいの実力なのですが、奥が深くまだまだ学べることがたくさんありそう。</p> このすみ tag:crieit.net,2005:PublicArticle/15024 2019-05-25T13:19:11+09:00 2019-06-06T08:03:20+09:00 https://crieit.net/posts/POCO-static-link POCO を static に link する <h1 id="結論"><a href="#%E7%B5%90%E8%AB%96">結論</a></h1> <pre><code class="bash:">-Wl,--start-group -Wl,-Bstatic -lPocoFoundation -lPocoUtil -lPocoXML -lPocoJSON -lPocoNet -Wl,--end-group -Wl,-Bdynamic -lpthread </code></pre> <p>今世のリンカオプションには <code>--start-group, --end-group</code> なんて便利なものがあるんですね</p> <h1 id="はじめに"><a href="#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB">はじめに</a></h1> <p><a href="https://crieit.net/posts/C-Cerflet">Cerflet</a> ベースの WebApplication を deploy しようとして、POCO に依存してしまうのもアレだなと思い、だったら static に link してしまおうと思ったのが事の発端です</p> <h2 id="POCO の static library を make"><a href="#POCO+%E3%81%AE+static+library+%E3%82%92+make">POCO の static library を make</a></h2> <p>POCO の configure の <a target="_blank" rel="nofollow noopener" href="https://github.com/pocoproject/poco/blob/develop/configure#L117">--static</a> オプションを使って make します</p> <pre><code class="bash:">./configure --static make </code></pre> <p>はじめは shared library 作る時と同じで <code>make -j4</code> ってやってたんですけどリンクエラーがでるので、多分、static に link してるから順番とかが影響してるんだろうなと深く考えずに <code>make</code> にしたらでなくなりました<br /> こんな些細なところからすでにlink する時の嫌な事が始まってます ^^;;;</p> <h2 id="しっかりハマる"><a href="#%E3%81%97%E3%81%A3%E3%81%8B%E3%82%8A%E3%83%8F%E3%83%9E%E3%82%8B">しっかりハマる</a></h2> <p>マジメな C++ プログラマだった頃の辛い思い出が蘇ってきます...</p> <h3 id="pthread がない"><a href="#pthread+%E3%81%8C%E3%81%AA%E3%81%84">pthread がない</a></h3> <p>dynamic に link した時と同じ感覚で素朴に lPocoFoundation をリンクしようとしたのですが</p> <pre><code class="bash:">g++ -o hellocerflet_s HelloCerflet.cpp ../lib/httpcerflet.cpp -I../lib/ -L/usr/local/lib -lPocoFoundation -static Thread.cpp:(.text+0x1ec): undefined reference to `pthread_setspecific' Thread.cpp:(.text+0x228): undefined reference to `pthread_sigmask' Thread.cpp:(.text+0x30c): undefined reference to `pthread_mutex_lock' Thread.cpp:(.text+0x328): undefined reference to `pthread_cond_broadcast' Thread.cpp:(.text+0x338): undefined reference to `pthread_mutex_unlock' ... </code></pre> <p>-lpthread つけてやらないといけないんですね</p> <h3 id="Poco 自身の依存関係"><a href="#Poco+%E8%87%AA%E8%BA%AB%E3%81%AE%E4%BE%9D%E5%AD%98%E9%96%A2%E4%BF%82">Poco 自身の依存関係</a></h3> <p>で、-lpthread つけてあげたんですが</p> <pre><code class="bash:">g++ -o hellocerflet_s HelloCerflet.cpp ../lib/httpcerflet.cpp -I../lib/ -L/usr/local/lib -lPocoFoundation -static -lpthread httpcerflet.cpp:(.text+0x54): undefined reference to `Poco::Util::Application::loadConfiguration(int)' httpcerflet.cpp:(.text+0x64): undefined reference to `Poco::Util::Application::initialize(Poco::Util::Application&)' /tmp/ccZExLN3.o: In function `HttpCerflet::uninitialize()': httpcerflet.cpp:(.text+0x8c): undefined reference to `Poco::Util::Application::uninitialize()' ... </code></pre> <p>あ、static link だから lPocoFoundation が依存する Poco のライブラリも先にリンクしておいてあげないと...</p> <h3 id="link の順番"><a href="#link+%E3%81%AE%E9%A0%86%E7%95%AA">link の順番</a></h3> <p>で、undefined だって言われる Poco のライブラリをどんどん前に追加しているのに、まだ undefined が...</p> <pre><code class="bash:">g++ -o hellocerflet_s HelloCerflet.cpp ../lib/httpcerflet.cpp -I../lib/ -L/usr/local/lib -lPocoXML -lPocoJSON -lPocoUtil -lPocoNet -lPocoFoundation -static -lpthread ... JSONConfiguration.cpp:(.text+0x6a0): undefined reference to `Poco::JSON::Query::~Query()' ... XMLConfiguration.cpp:(.text+0x1cc): undefined reference to `Poco::XML::Document::documentElement() const' </code></pre> <p>ちゃんと -lPocoXML も -lPocoJSON も link してるのになんで undefined なんて言われるんだろ?<br /> このあたりでもう考えるのが嫌になって POCO static link とかでググるとそのものズバリなのが<br /> <a target="_blank" rel="nofollow noopener" href="https://kotaeta.com/55682155">定義されていないシンボルへのPoco C++ 静的リンクの問題</a></p> <p>そうだ、<strong>リンクの順番!使われる前にリンクしておかないといけない</strong>んでした</p> <h3 id="glibc の静的リンク"><a href="#glibc+%E3%81%AE%E9%9D%99%E7%9A%84%E3%83%AA%E3%83%B3%E3%82%AF">glibc の静的リンク</a></h3> <p>POCO内部の依存関係に合わせて正しい順番でリンクすると</p> <pre><code>g++ -o hellocerflet_s HelloCerflet.cpp ../lib/httpcerflet.cpp -I../lib/ -L/usr/local/lib -lPocoUtil -lPocoXML -lPocoJSON -lPocoNet -lPocoFoundation -static -lpthread /usr/local/lib/libPocoFoundation.a(Path.o): In function `Poco::PathImpl::homeImpl[abi:cxx11]()': Path.cpp:(.text+0x220): warning: Using 'getpwuid' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking </code></pre> <p>glibc まで static にリンクしようとしてました ^^;;;</p> <h3 id="第一次正解"><a href="#%E7%AC%AC%E4%B8%80%E6%AC%A1%E6%AD%A3%E8%A7%A3">第一次正解</a></h3> <p>なので、pthread だけは dynamic に link するようにして</p> <pre><code class="bash">g++ -o hellocerflet_s HelloCerflet.cpp ../lib/httpcerflet.cpp -I../lib/ -L/usr/local/lib -Wl,-Bstatic -lPocoUtil -Wl,-Bstatic -lPocoXML -Wl,-Bstatic -lPocoJSON -Wl,-Bstatic -lPocoNet -Wl,-Bstatic -lPocoFoundation -Wl,-Bdynamic -lpthread </code></pre> <p>やっとできました</p> <h1 id="ちょっと考察"><a href="#%E3%81%A1%E3%82%87%E3%81%A3%E3%81%A8%E8%80%83%E5%AF%9F">ちょっと考察</a></h1> <p>しかし今どきリンクの順番みたいな機械的に解決できることに人間が頭を使わないといけないのってちょっと残念ですよね、人って機械的な作業が苦手なクリエイティブなクリーチャーなのに</p> <p>でも、さすがになにか進歩してるんじゃないかとおもって static link order とかでググりまくってると <a target="_blank" rel="nofollow noopener" href="https://stackoverflow.com/questions/45135/why-does-the-order-in-which-libraries-are-linked-sometimes-cause-errors-in-gcc">Why does the order in which libraries are linked sometimes cause errors in GCC?</a><br /> やっぱり人類は賢かった!<strong>--start-group, --end-group</strong> なんてリンカのオプションをつくってくれた人がいて、この中だと順番気にしなくてもリンカがよしなにやってくれるんですね!</p> <p>で、本稿の結論にいたります</p> <h2 id="再度、結論"><a href="#%E5%86%8D%E5%BA%A6%E3%80%81%E7%B5%90%E8%AB%96">再度、結論</a></h2> <pre><code class="bash:">-Wl,--start-group -Wl,-Bstatic -lPocoFoundation -lPocoUtil -lPocoXML -lPocoJSON -lPocoNet -Wl,--end-group -Wl,-Bdynamic -lpthread </code></pre> <h1 id="感想"><a href="#%E6%84%9F%E6%83%B3">感想</a></h1> <p>まるで紅茶に浸した一匙のマドレーヌを口に含んだ時みたいに鮮明に記憶が戻ってきました<br /> 私は gcc のこういう所があんまり好きじゃなかったんでした</p> Dr. Takeyuki Ueda tag:crieit.net,2005:PublicArticle/14937 2019-04-20T12:08:57+09:00 2019-07-02T19:43:14+09:00 https://crieit.net/posts/C-Cerflet C++ ベースのウェブアプリケーションサーバ Cerflet のご紹介 <h1 id="はじめに"><a href="#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB">はじめに</a></h1> <p><a target="_blank" rel="nofollow noopener" href="https://github.com/MayaPosch/Cerflet">Cerflet</a> は <a target="_blank" rel="nofollow noopener" href="https://github.com/MayaPosch">Maya Posch</a> さん作の C++ ベースのシンプルな Web Application server です<br /> Raspberry Pi でもサクサクに動いています</p> <p>python の tornado みたいにリクエストハンドラを書くだけで簡単に使える上に、<strong>オール C++</strong> かつ<strong>オンメモリ</strong>なので超高速が期待できます</p> <p>ちなみに Cerf はジビエ好きな方はピンと来るかと存じますが多分、フランス語の <strong>鹿(セール)</strong> なんじゃないかなと想像してます、Maya さんの他のプロダクトも動物の名前のが多いし、彼女の会社の名前からして <a target="_blank" rel="nofollow noopener" href="http://www.nyanko.ws">Nyanko</a> だし</p> <h1 id="実装"><a href="#%E5%AE%9F%E8%A3%85">実装</a></h1> <p>本体の<a target="_blank" rel="nofollow noopener" href="https://github.com/MayaPosch/Cerflet/blob/master/lib/httpcerflet.cpp">実装</a>は物凄くシンプルでコメント込で 80行ぐらいしかないです、すごい<br /> 私だったら C++ の80行ってコマンドライン処理するだけでもゆうに超えちゃったりします</p> <p>サーバの処理も実行時オプションの処理も <a target="_blank" rel="nofollow noopener" href="https://pocoproject.org/">POCO</a> の機能が有効に使われてて、POCO の凄さと、POCOを使えば Web Application でさえこんなにシンプルにつくれるという Maya さんのソフトウェア・アーキテクチャのセンスの良さに敬服いたしますとともに、Poco.Net のプラグマティックなチュートリアルとして大変ありがたく読ませていただきました次第でございます</p> <h1 id="How to try it"><a href="#How+to+try+it">How to try it</a></h1> <ol> <li>POCO を<a target="_blank" rel="nofollow noopener" href="https://pocoproject.org/download.html">インストール</a></li> <li>git clone https://github.com/MayaPosch/Cerflet.git</li> <li>cd Cerflet/sample</li> <li>make</li> <li>./hellocerflet</li> </ol> <p>「libPocoNet.so.60 がないよ」とかエラーになるようでしたら <a href="https://crieit.net/posts/POCO-error-while-loading-shared-libraries-libPocoNet-so-60-cannot-open-shared-object-file-No-such-file-or-directory">ldconfigして</a>みてください</p> <p>で、hellocerflet を起動したサーバの port 8080 番をブラウザで開くと</p> <p><a href="https://crieit.now.sh/upload_images/7cc81f710697ae3e872d25b283d8f9535cba83edb5f74.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/7cc81f710697ae3e872d25b283d8f9535cba83edb5f74.png?mw=700" alt="スクリーンショット 2019-04-20 11.27.15.png" /></a></p> <p><strong>ビックリするほど簡単</strong>です</p> <p><a target="_blank" rel="nofollow noopener" href="https://github.com/MayaPosch/Cerflet/blob/master/sample/HelloCerflet.cpp#L22">こちら</a> の HTTPRequestHandler の中身を変えて、たとえば ContentType を "text/html" じゃなくて <strong>"application/json"</strong> にして、<a target="_blank" rel="nofollow noopener" href="https://github.com/MayaPosch/Cerflet/blob/master/sample/HelloCerflet.cpp#L32">ostr</a> に <strong>json 文字列</strong>を返したら超高速かつコンパクトな API サーバーとしてすぐにでも大活躍しそうです</p> <h1 id="作者の御紹介"><a href="#%E4%BD%9C%E8%80%85%E3%81%AE%E5%BE%A1%E7%B4%B9%E4%BB%8B">作者の御紹介</a></h1> <p>作者の <a target="_blank" rel="nofollow noopener" href="https://github.com/MayaPosch">Maya Posch</a> さんですが、<a target="_blank" rel="nofollow noopener" href="http://www.mayaposch.com/autobiography.php">御本人のブログ</a>によると生まれつきに抱えるいくつかの問題、特に<strong>両性具有</strong>に起因する問題(当時のニュース番組が<a target="_blank" rel="nofollow noopener" href="https://www.youtube.com/watch?v=M4N-0CgUCX8">これ</a> とか <a target="_blank" rel="nofollow noopener" href="https://www.youtube.com/watch?v=DKW2c0H2iGw">これ</a> とか残ってます)で祖国オランダを離れざるを得ず、安住の地を求めて世界を旅しながら自分の会社 <a target="_blank" rel="nofollow noopener" href="http://www.nyanko.ws/">Nyanko</a> を運営しつつプログラミングと電子工作に関する<a target="_blank" rel="nofollow noopener" href="http://www.mayaposch.com/index.php">数々のプロダクトと著作</a>を世に出していらっしゃいます<br /> まるで物語みたいに数奇な人生を歩みながら outcomes を出されていることに正直圧倒されてしまいました、すごい人がいるもんなんだなぁ<br /> 翻って自分を鑑みるにいったい何をやってるんだと情けなく忸怩たる思いに至る次第です</p> <p>近著 <a target="_blank" rel="nofollow noopener" href="https://learning.oreilly.com/library/view/hands-on-embedded-programming/9781788629300/">Hands-On Embedded Programming with C++17</a> を魅力的なタイトルに惹かれて読んだのが彼女を知るきっかけだったんですが、この本も POCO の紹介をふくめて Raspberry Pi みたいなSBC でプロダクトをつくる上でのオリジナルな話題にあふれていてとても面白い本でした</p> <h1 id="感想"><a href="#%E6%84%9F%E6%83%B3">感想</a></h1> <p>数日前に<a href="https://crieit.net/posts/Nuitka-python-code">某所</a>で「C++でウェブアプリ書く気にはならないし」なんて言っちゃったの、謹んで取り消させてください</p> <p>読書は時として人の世界観をダイナミックに変えてしまうものなのです ^^;;;;;;;</p> Dr. Takeyuki Ueda tag:crieit.net,2005:PublicArticle/14935 2019-04-20T09:56:19+09:00 2019-07-02T19:30:15+09:00 https://crieit.net/posts/POCO-error-while-loading-shared-libraries-libPocoNet-so-60-cannot-open-shared-object-file-No-such-file-or-directory POCO を使おうとして error while loading shared libraries: libPocoNet.so.60: cannot open shared object file: No such file or directory みたいに「ないよ」って言われる時 <p>こちらの皆様の雰囲気と合っていないようなので<a target="_blank" rel="nofollow noopener" href="http://www.uedasoft.com/2019/07/02/poco-を使おうとして-error-while-loading-shared-libraries-libpoconet-so-60-cannot-open-shared-object-file-no-such-file-or-directory-み/">こちら</a>に移動致しました</p> Dr. Takeyuki Ueda