さてさて、ネイティブDLLを作って、Windows PhoneのC#プロジェクトへ組み込み、いざデバッグすると驚愕。ネイティブコード側に仕込んでおいたはずのOutputDebugStringの出力がまったくないではありませんか。
思わずかっとなって、マネージ側でDebug.WriteLineを呼ぶだけのクラスを作って、ネイティブ側に渡しておく仕組みを作っていました。この試行錯誤で土日が潰れました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | interface __declspec(uuid("95E19FD5-D011-4979-BBFB-26D9C358BDC0")) IDebug : IUnknown { // このマクロはこう展開される // virtual HRESULT STDMETHODCALLTYPE WriteLine(BSTR s) = 0; STDMETHOD(WriteLine)(BSTR s) PURE; STDMETHOD(WriteLineW)(LPCWSTR s) PURE; }; ATL::CComPtr<IDebug> g_Debug; HRESULT DebugWriteLineF(LPCWSTR format, ...) { WCHAR buffer[1024]; std::va_list arg; va_start(arg, format); int size = wvsprintf(buffer, format, arg); if (size > 0) { ATL::CComBSTR str(size, buffer); return g_Debug->WriteLine(str); } else { return ATL::AtlHresultFromLastError(); } } |
ついでにprintf風出力も作っておきました。実行ファイルの容量を考慮し、Windows APIのwvsprintfを使っています。
そしてマネージ側です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | [ComImport, Guid("95E19FD5-D011-4979-BBFB-26D9C358BDC0"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IDebug { void WriteLine([In, MarshalAs(UnmanagedType.BStr)] string s); void WriteLineW([In, MarshalAs(UnmanagedType.LPWStr)] string s); } sealed class DebugImpl : IDebug { public void WriteLine(string s) { Debug.WriteLine(s); } public void WriteLineW(string s) { Debug.WriteLine(s); } } |
本当はMarshalAs(UnmanagedType.LPStr)なWriteLineAも追加しようとしたのですが、駄目だったのは昨日の記事に書いたとおりです。
あとは、マネージ側からネイティブ側へDebugImplオブジェクトを渡せば完了です。適当なインタフェース・クラスを作ってやりましょう。渡す際の引数は、マネージ側:[In] IDebug、ネイティブ側:IDebug*の引数で大丈夫です。
スポンサード リンク |
True Audio (TTA)という可逆圧縮の音声形式があります。はい、つまりWindows PhoneでTTAの再生ができるかどうかちょっと試してみました。結論から言うと、ハマりどころもなく簡単にできました(まだいろいろと工夫の余地はありますが)。……