Qt QuickでUWPネイティブAPIを呼び出す
Call UWP native APIs from Qt
Windows 10で動作するUnivwersal Windows Platform Appではマイクロソフトの独自拡張プログラム言語「C++/CX」による開発がサポートされています。COMによる純粋なC++でUWPアプリを開発することも不可能ではありませんが、非同期処理やランタイムライブラリーの取り扱といったUWP固有の取り決めをスムーズに取り入れることができるので、Qt WinRTでUWPのネイティブAPIを組み込みたい場合は、C++/CXでコーディングしたほうが効率が良いと思います。
MSVCコンパイラでは「ZW」オプションを加えることでC++/CX拡張のコードも扱えるようになります。よって、QtでC++/CXを使うにはプロジェクトファイルでC++オプションを追加します。
winrt{
QMAKE_CXXFLAGS += -ZW
}
C++/CXによるクラス宣言や非同期処理のプログラム方法は
UWP・C#プログラマーのためのC++/CX基礎知識にまとめていますので、こちらもご一読ください。
文字列をQtとC++/CXでやり取りしたいときは、utf16形式に変換して文字列クラスを作成・複製します。
string.cpp
String ^cxstr = "Test";
// WinRT文字列オブジェクトでは、Data()でUTF16形式の文字配列を取得できる
QString qstr = QString::fromWCharArray(str->Data());
// 同様にQString::utf16からwchar_tの文字配列を取得してStringオブジェクトを新規作成する
String ^nstr = nullptr;
cxstr = ref new String((const wchar_t*)qstr.utf16());
WinRT C++オブジェクトに組み込んだ普遍的なC++クラスをパブリックな変数や関数として公開することは禁止されているので、C++/CXクラスでQObject派生クラスを取り扱いたいのであればfriendを活用するのがよいでしょう。
winrt.cpp
// C++(QObject)派生クラスの定義
class Controller : public QObject
{
Q_OBJECT
private:
InputDevice ^gidev = nullptr;
public:
void begin()
{
gidev = ref new InputDevice();
// 自身のC++クラスをfriendより登録
gidev->gc = this;
gidev->Start();
}
void postHat(quint8 n)
{
// ここでQQuickItemなどに入力データを送る
}
}
// WinRTオブジェクトの定義
ref class InputDevice sealed
{
friend class Controller;
private:
HidDevice ^device = nullptr;
Controller *gc = nullptr;
public:
void Start()
{
// HIDデバイスを検索するプログラム例
auto selector = HidDevice::GetDeviceSelector(0x1, 0x4);
task<DeviceInformationCollection^> c =
create_task(DeviceInformation::FindAllAsync(selector));
c.then([this](DeviceInformationCollection^ info){
// 列挙したデバイスから使用したデバイスを取得してイベントを登録するが、ここでは割愛。
});
}
void OnInputReportReceived(HidDevice ^sender, HidInputReportReceivedEventArgs ^args)
{
// HIDデバイスから入力を受け取ったら発生するイベント
gc->postHat(0);
}
}
2018/11/12