QxOrm で簡単なサンプルを書いてみる

以前に書いた QxOrm の記事が(日本においてはおそらく)最初の解説記事だったらしく、ちょいちょい反応があった。

ネット上でも gitlove さんという方が、簡単なサンプルを書いてくれた。

クラスの定義や main 関数での QxOrm の操作はそこに書かれているコードほぼそのままでいいと思います。

ただ、(チュートリアルでもあまり強調されていないが)QxOrm を使う際のオマジナイみたいなもので、export.h というファイルが必要なようです。

target = test としたとき、まず .pro ファイルで _BUILDING_TEST を定義しておき、export.h で各種マクロを定義します。

具体的には以下の通り。

//export.h
#ifndef _QX_TEST_EXPORT_H_
#define _QX_TEST_EXPORT_H_

#ifdef _BUILDING_QX_TEST
#define QX_TEST_DLL_EXPORT QX_DLL_EXPORT_HELPER
#else
#define QX_TEST_DLL_EXPORT QX_DLL_IMPORT_HELPER
#endif

#ifdef _BUILDING_QX_TEST
#define QX_REGISTER_HPP_QX_TEST     QX_REGISTER_HPP_EXPORT_DLL
#define QX_REGISTER_CPP_QX_TEST     QX_REGISTER_CPP_EXPORT_DLL
#else
#define QX_REGISTER_HPP_QX_TEST     QX_REGISTER_HPP_IMPORT_DLL
#define QX_REGISTER_CPP_QX_TEST     QX_REGISTER_CPP_IMPORT_DLL
#endif

#endif

このファイルを precompiled.h に include しておき、main から使えるようにしておく、という構成です。

マクロを定義したので、ソースも適宜変更。

//person.h
#ifndef _CLASS_PERSON_H_
#define _CLASS_PERSON_H_

class person
{
public:

   long id;
   QString name;

   person() :id(0) { ; }
   virtual ~person() { ; }

};

QX_REGISTER_HPP_QX_TEST(person, qx::trait::no_base_class_defined,1)//←これを追加

#endif // _CLASS_PERSON_H

person.cpp も以下のように変更。


#include "../include/precompiled.h"

#include "../include/person.h"

#include <QxOrm_Impl.h>

QX_REGISTER_CPP_QX_TEST(person)//←追加

namespace qx {
template &lt;> void register_class(QxClass<person> & t)
{
   t.id(& person::id, "id");

   t.data(& person::name, "name");
}}

main.cpp


#include "../include/precompiled.h"

#include <QtCore/qcoreapplication.h>
#include "../include/person.h"

#include <QxOrm_Impl.h>

int main(int argc, char * argv[])
{
   // Qt application
   QCoreApplication app(argc, argv);
   QFile::remove("./person.db");

   typedef std::shared_ptr<person> person_ptr;
   person_ptr d1; d1.reset(new person()); d1->name = "name1";

   typedef std::vector<person_ptr> type_lst_person;
   type_lst_person lst_person;
   lst_person.push_back(d1);

   // Parameters to connect to database
   qx::QxSqlDatabase::getSingleton()->setDriverName("QSQLITE");
   qx::QxSqlDatabase::getSingleton()->setDatabaseName("./person.db");
   qx::QxSqlDatabase::getSingleton()->setHostName("localhost");
   qx::QxSqlDatabase::getSingleton()->setUserName("root");
   qx::QxSqlDatabase::getSingleton()->setPassword("");
   qx::QxSqlDatabase::getSingleton()->setFormatSqlQueryBeforeLogging(true);
   qx::QxSqlDatabase::getSingleton()->setDisplayTimerDetails(true);

   // Only for debug purpose : assert if invalid offset detected fetching a relation
   qx::QxSqlDatabase::getSingleton()->setVerifyOffsetRelation(true);

   // Create all tables in database
   QSqlError daoError = qx::dao::create_table<person>();

   person_ptr person_1; person_1.reset(new person());
   person_1->id = 1; person_1->name = "秋葉 太郎";

   daoError = qx::dao::insert(person_1);

   return 0;
}

これで、ビルドして、実行すると出力先に test(d) という実行ファイルと person.db という sqlite のデータベースができているはずです。

DB Browser for SQLite などで覗いてみると…

できてますね!

注意点

①上では、従来の .pro ファイルを使う qmake でビルドしています。

なのですが、cmake でビルドしようとすると QxOrm のライブラリが見つからない場合があるようです。

これは QxOrm の cmake ビルドシステム自体が未整備のためのようです。関連の PR がありました。

開発者さん自身は、しばらくは qmake メインでいきたいようです。

ワイは、こんなことを提案してきました。

cmake が他のパッケージをどうやって探しているかまっっったく理解してませんが。

参考:

https://qiita.com/shohirose/items/d9bda00a39a113965c5c

②他には postgreSQL が繋がらないかな。

qx::QxSqlDatabase::getSingleton()->setDriverName("QPSQL");

としたでのは、ドライバーがロードできない云々というエラーが出る。

Qt あれこれ

久方ぶりに Qt を触っているんだが、Qt 自体は進化している。

日本の Qt 事情

なのだが、日本の Qt 事情はお寒い。

まず、日本語で書かれたオリジナルの Qt 関係の本はほぼない。

唯一あるとすれば、これ↓。

まあ入門書でしょう。→ 括りとしては入門書なのでしょうが、細部に著者の Qt に対する洞察が散りばめられており、ここら辺は入門書の範疇を超えています。

レビューにもあるように

なお、表紙、裏表紙、背表紙すべてにあるロリ絵はやめて欲しいです。 恥ずかしい事この上ありません。 なぜ技術本にロリ絵を付けないといけないのかさっぱりわかりません。

ロリ絵というかアニメ絵というか。

頭のあたりに注目するとウマ娘意識してんのかな?と思わないでもない。

装丁は、まあ、賛否分かれるでしょう。

確かに Qt6 になって、Qt Creator の操作性はけっこう変わっている。

QML

一昔前の Qt GUI というと Qt Widget だったが、QML もかなり成長しているようだ。

この記事でも、将来は QML だろう、みたいなことが書かれている。

確かに、これはそうだよなあ。

Web アプリの作り方は、ほぼ大筋が固まっている。バックエンドとフロントエンド、UI とロジックの分離などなど。

このおかげで何をどうやって作成するのかという目標が持ちやすい。

おまけにブラウザの表現力は年々上がってきているし。

比較するのもアレだが Java の GUI 環境なんて今では陳腐に見える。

デスクトップもこの感覚で作りたい、というのは、当然の流れのように思える。

Qt5 → Qt6 何が変わったか?

vector の(内部的な)取り扱いが変わった。

上の本でも触れられているが、

#include <QCoreApplication>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QVector vector;
    vector << 1 << 2;
    qDebug() << vector;


    return a.exec();
}

を走らせると QVector(1, 2) ではなくて

QList(1, 2)

と表示される。
要するに Qt5 時代の List を Vector にした模様。

 

Qt の ORM QxOrmを使ってみる

Qt の Orm である QxOrm を使ってみたくなったので、MacOS にインストールを試みた。

あらかじめ言っておきますが、試みただけで、(動くことは動いたが)完全にうまくいったというわけではないので念の為。

この手のややマイナーなソフトはメンテなどが手薄な感は否めない。

トライアル1

手順は QxOrm の公式ページで案内されている。

案内は windows のみなので、Mac の場合は適宜読み換える。

1 まず、Qt をインストール。

ここは問題ないでしょう。ただし、Qt5 で説明しているが、現在(2023/1月頃)の最新版は 6.2.4 である。
後で説明すると思うが、Qt6 では、このバージョン(1.4.8)はビルドできないことがわかっている。

2 qmake がコマンドラインから使えるように  PATH を修正。

今後のことを考えるとここはやっておいた方がいいでしょう

3, 4 boost の lib_shared を使えるようにしておく(optional)

ただし、boost は必須ではない。開発者も言っているが、ビルドできるかもわからない段階で無理してこの機能を試す必要性は薄い。

5 QxOrm 本体のダウンロード

ダウンロードページはこちら。これを書いている時点でのバージョンは 1.4.8 。

6 boost を使う場合は、QxOrm の QxOrm.pri を適宜編集

上で触れたように、ここは飛ばしましょう。

7 QXORM_DIR を環境変数に加える。

ここはやっておきましょう。

この後、8, 9, 10 とサンプルを試す手順が説明されているのだが、当たり前だが、QxOrm のライブラリ自体が構築されていないのでリンカエラーが出る。

というわけで、ライブラリを構築する。。。のだが、ここでエラー。

打開策

GitHub にいくと、Unable compile QxOrm1.4.8 というド直球な issue が立っている。

開発側は

I can build QxOrm and all examples without any issue with Qt 6.2.3, so I think it should be OK with Qt 6.2.4 (if you download latest version on GitHub, which should be : QxOrm_1.4.9_BETA_18)

と、1.4.9 を使えと言っている。

しかし、有償のライセンス(無償と有償のダブルライセンス)もあるのに、これはいかんのでは?と思わないでもない。

トライアル2

というわけで、GitHub から 1.4.9 を落としてきて、ビルド。

 

今度は、ビルド成功。

添付のサンプルを動かしたみた限りでは動作も問題なさそう。

wt::dbo vs odb vs QxOrm

ところで、C++ の ORM は定番というものがない。

QxOrm, odb, wt::dbo あたりがそこそこは知られているのだが、wt::dto の作者さんがユーザーさんの質問に答える形で3者の相違について語ってます。(→ 記事

 

Qt

最近、すっかりご無沙汰の Qt。

睡魔と戦いながら、boost と Qt をインストール。

経験ある人ならわかると思うが、両者のインストール時間は極めて長い。

薄れいく意識の中、操作をしていたので、起きたら、どこに Qt をインストールしたのかわからなくなったw

デフォルトだとホーム直下に Qt というフォルダがつくられ、その中に Qt Creator がある。

ライセンス

わかりにくいと評判の Qt で作成したアプリのライセンス。

ええと、これ、Qt でスタティックライブラリでアプリを作るのでなければ、LGPL っすよね。

Qt で作成した部分に関しては、公開の義務なし。

「スタティックライブラリでなければ」と書いたが、公式にもスタティックのライブラリ群は提供されておらず、意識的に(かなり苦労して)スタティックライブラリでアプリを構築する以外はダイナミックリンクで作成せざるを得ない。

実質、LGPL っすよね。

なんであんなわかりにくい書き方するんだろ?

サンプル

なんやかんやで環境は整ったので、サンプルを実行。

M1/M2 Mac でも普通に 3D が描画できているのはエラい。

基本事項のおさらい

IDE は Qt Creator だが、ビルドシステムで qmake を選んだ場合は qmake で ****.pro を走らせている。

実際にはもうちょっと複雑なビルドシステムになっている。

なお ****.pri は PRojectInclude ファイルの略。

Qt6 からは、ビルドに cmake を選べるようになった。この場合は、当然、CMakeLists.txt を使っている。

試しにこちらのオプションでハロワしたが、いや、ほんと、普通の cmake プロジェクト。