SkypeAPI格闘日記

予告通り今日は1日SkypeAPIと戦っておりました。

まずは関連ブックマーク。

  • Skype
  • ここで配布されているSkypeをインストールすると、APIも一緒にインストールされるようです。

  • Japanese Skype Developers Forum
  • 日本人開発者向けの日本語のフォーラムです。まだ出来たてなので情報は少ないですが、これからに期待です。

  • s@s
  • Skype社員である岩田さんのブログです。彼はSkypeの開発者とSkypeAPIを使う側の開発者との橋渡しをしてくれている人です。

  • Share Skype : Documentation
  • ここにSkypeAPIリファレンス(PDF)とサンプルプログラムがあります。今日はこのサンプルと格闘していました。

  • SkypeAPI入門(日本語)
  • SkypeAPIの使い方を日本語で丁寧に説明してあるPDFファイルです。SkypeAPIを使おうと思ったらまず一読しましょう。

  • KhaosLabs
  • COM Wrapperを配布されているサイトらしいのですが、今回僕は使っていません。


ざっと調べた情報と昨日聞いてきた情報をあわせると、SkypeAPIはどうやらメッセージという形で扱うらしいです。
WindowsのGUIアプリケーションは、マウスクリックやウィンドウの移動など、何かが起こった時にOSからメッセージを送ってもらい、これを処理することで動いています。1
ここで言うメッセージとは、たぶんそれのことだと思うのですが、SkypeAPIでは、メッセージを使って命令の書かれた文字列を送り、それによってSkypeを制御するんだそうです。

しかし、メッセージの送受信はC/C++でしか行うことが出来ない上、処理が面倒なので、COM Wrapperを使うことが推奨されているようでした。
COMというのはWindowsの技術で、僕も詳しいことはまだよく知らないのですが、処理を代行してやってくれる部品みたいな物なのかな?2
COMの形にすれば、C/C++以外でも、VBやPHP、C#、Perlなど様々な言語から扱えるようになると書いてありました。

けど、、、メッセージって別にC/C++じゃなくてもWin32APIが使える言語だったら何でも使えるんじゃないの??
よく分からないのですが、COMを使っちゃうと、開発側だけでなく利用者側にも同じCOMをインストールしなくちゃならないんじゃないかな?
もしそうだとしたら、COMを使わずに出来ることだったら、使わずに済ませちゃいたいです。
文字列処理と聞いて真っ先にC#が頭に浮かんだのですが3、メッセージを扱うだけならC#でも出来ます。
そこで、とりあえず実際にどんな方法でやりとりするのか、サンプルコードを見て調べてみることにしました。

今回参考にしたサンプルは、上でも書いたここにあったExample C++ code for Windows

テキストエディタでのデバッグは面倒なので、とりあえずVisualStudioで新しいソリューションを作り、そこにサンプルに含まれてたmsgapitest.cppを追加します。
とりあえずmain関数があったので、そこから1行ずつ見ていき、動作をひとつずつ調べていきました。

いきなり_beginthreadなんて関数が出てきてびびったのですが、どうやらSkypeからの受信と送信(及びコンソールからの入力)を別のスレッドで動かしているようです。
そうして処理ひとつひとつにざっとコメントを付けていき、一通りのコメントが終わりましたが、特に変わったことはしていないので、C#でもCOM抜きで扱えそうです。
よかったよかった。

使ったことのないWin32APIもいくつか出てきていたので、次はコンパイルして実行してみることにしました。
ビルドボタンをぽちっと。

早速_beginthread関数が見付からないと怒られました。
そうだった、スレッドを使うプログラムの場合、プロジェクトの設定をマルチスレッドにしなくてはならないのでした。
手順はGoogleったら出てきたこちらを参考に以下のように設定。4

1.メニューの「プロジェクト」→「設定」をクリック。
  「プロジェクトの設定」ダイアログが出てきます。
2.「C/C++」タブを選びます。
3.カテゴリ(Y)のコンボボックスから、「コード生成」を選びます。
4.使用するランタイムライブラリの中から、
  デバッグ構成の場合は、「マルチスレッド(デバッグ)」を、
  リリース構成の場合は、「マルチスレッド」を選びます。

さて、これでビルド通るかな~
と思ったら、次に出たのがリンクエラー。

リンクしています...
msgapitest.obj : error LNK2019: 未解決の外部シンボル __imp__RpcStringFreeA@4 が関数 "bool __cdecl Initialize_CreateWindowClass(void)" (?Initialize_CreateWindowClass@@YA_NXZ) で参照されました。
msgapitest.obj : error LNK2019: 未解決の外部シンボル __imp__UuidToStringA@8 が関数 "bool __cdecl Initialize_CreateWindowClass(void)" (?Initialize_CreateWindowClass@@YA_NXZ) で参照されました。
msgapitest.obj : error LNK2019: 未解決の外部シンボル __imp__UuidCreate@4 が関数 "bool __cdecl Initialize_CreateWindowClass(void)" (?Initialize_CreateWindowClass@@YA_NXZ) で参照されました。
Debug/SkypeAPI-Sample_win.exe : fatal error LNK1120: 外部参照 3 が未解決です。

Googleで検索してみたら、こんな記事を見付けたので試してみました。
プロジェクトにリンクさせるには、どこかの設定をいじるらしいのですが、その方法を知らないので、僕はいつも次の方法を使っています。

#pragma comment(lib, "rpcrt4.lib")

これをソースの中に書いておけばおっけーです。
Microsoftはこの方法を推奨していないそうですが、こっちの方法の方が断然便利です。

さて、ビルド開始。
printfに対してwarning5が少し出たものの、なんとか無事ビルドすることが出来ました。

これでSkypeとの送受信のメッセージの方法は分かったので、次はC#で書いてみようかな。

一応コメント付けたソースファイルも置いておきますね。
msgapitest.cpp
ライセンス的にマズかったらごめんなさい。言ってくれればすぐ消します。
あと、間違ってたらごめんなさい。m(_ _)m

  1. 詳しくはこちらで勉強してください → 猫でもわかるプログラミング
  2. あの有名なDirectXもCOMオブジェクトです。
  3. C/C++での文字列処理はかなりめんどい。
  4. VisualStudio .NET 2003だとちょっと違ったけどほぼ一緒でした。
  5. warning C4313: 'printf' : 書式文字列内の '%X' が '<不明>' 型の引数 1926057056 と競合しています。

コメントを残す