[left] [up] [right]

アプリケーションの作成方法

idnkitライブラリ (およびidnkitliteライブラリ) を用いたアプリケーション の作成方法や注意点をまとめました。

プログラムの書き方

idnkitライブラリ (およびidnkitliteライブラリ) を使用したプログラムの 作成方法、および注意点などについてまとめておきます。

ヘッダファイル

高レベルAPIを使用するプログラムでは、idn/api.hを インクルードしてください。 (エラーコードを定義しているidn/result.hは、 idn/api.hから暗黙的にインクルードされるため、明示的に インクルードする必要はありません。)

#include <idn/api.h>

低レベルAPIを使用するプログラムでは、idn/res.hを インクルードしてください。 (変換コンテキストを操作するresconfモジュールのヘッダファイル idn/resconf.hやエラーコードを定義している idn/result.hは、idn/res.hから暗黙的に インクルードされるため、明示的にインクルードする必要はありません。)

#include <idn/res.h>

バージョン番号の取得関数を提供しているversionモジュールを使う場合は、 別途idn/version.hをインクルードして下さい。

#include <idn/version.h>

ロケール設定

idnkitライブラリ (およびidnkitliteライブラリ) は、実行時に、 ローカルエンコーディングや「現在の言語」を決定する際、ロケールの 設定情報を参照します。 そのため、アプリケーションは冒頭部分でsetlocale()を 呼び出し、ロケールの初期化を行って下さい。 典型的な呼び出し方は、次のようになります。

setlocale(LC_ALL, "");

システムやCコンパイラによっては、setlocale()を使用する ためには

#include <locale.h>

という記述も別途必要かも知れません。 詳しくは、お使いのシステムないしCコンパイラのマニュアルを参照して下さい。

エラー表示

idnkitライブラリ (およびidnkitliteライブラリ) のほとんどのAPIは、 idn_result_t 型のエラーコードを返します。 エラーコードに応じたメッセージ文字列を返す関数 idn_result_tostring()が用意されています。 エラーメッセージを表示する際には、この関数を使うと便利です。 ただし、エラーメッセージはロケール設定によらず英語になります。

idn_result_t r;

/* idn_result_tostring() の使用例 */
r = idn_encodename(IDN_ENCODE_LOOKUP, from, to, tolen);
if (r != idn_success)
    printf("error: %s\n", idn_result_tostring(r));

この関数についての詳細は、 「idn_result_tostring()」 をご覧ください。

コンパイル

アプリケーションをコンパイルする際には、idnkitのヘッダファイルの 配置場所をCコンパイラに伝える必要があるかも知れません。 もし、Cコンパイラがヘッダファイルを見つけられなかった場合は、

error: idn/api.h: No such file or directory

といったエラーメッセージが出力されます。 (メッセージは、お使いのCコンパイラ等によって異なります。) GCCなど、UNIX系OSで動作する典型的なCコンパイラでは、 -Iオプションを使ってヘッダファイルの検索パスを指定 することができます。 たとえば、/usr/local/include/idnの下にヘッダファイル がインストールされている場合は (最後の/idnを取って)、

gcc -I/usr/local/include -c sample.c

のようにします。

リンク

GCCに代表される、UNIX系OSで動作する典型的なCコンパイラを用いて アプリケーションにidnkitライブラリをリンクする際は、-lidnkit というオプションを付与します。

gcc -o sample sample.o -lidnkit

ただし、GNU libiconvなどの外部ライブラリの提供するiconv() を利用した場合は、合わせてそのライブラリもリンクする必要があります。 たとえば、GNU libiconvであれば、次のようにします。

gcc -o sample sample.o -lidnkit -liconv

idnkitliteライブラリをリンクする際は、-lidnkitの代わりに -lidnkitliteオプションを付与します。 idnkitliteライブラリはiconv()を使用しませんので、 iconv()を提供するライブラリのリンクは必要ありません。

gcc -o sample sample.o -lidnkitlite

ただし、idnkitライブラリ、idnkitliteライブラリ、iconv() を提供するライブラリがすべて、Cコンパイラ (正確にはリンカ) が探し出せる 位置になくてはなりません。 見つからない場合は、

sample.c:(.text+0x19): undefined reference to `idn_nameinit'

といったエラーメッセージが出力されます。 その場合、 -Lオプションを使ってライブラリファイルの検索パスを 指定することができます。 たとえば、/usr/local/libの下にライブラリが インストールされている場合は、

gcc -o sample sample.o -L/usr/local/lib -lidnkit

のようにします。 ただし、共有ライブラリをリンクする際は、さらに幾つかの注意点があります。 詳しくは次項に記します。

共有ライブラリのリンク

共有ライブラリをリンクする際、システムによってはコンパイラやリンカに オプションを付与する必要があります。 ただ、必要となるオプションは、システムによってまちまちです。 調べてもよく分からなければ、GNU libtoolを使うのも一つの手です。 (ただし、GNU libtoolが対応しているシステムに限ります。) GNU libtoolは以下のページから入手できます。

http://www.gnu.org/software/libtool/

GNU libtoolを使用する場合、コンパイル時は次のように "libtool --mode=compile" に続けてCコンパイラのコマンド行を 記します。

libtool --mode=compile gcc -I/usr/local/include -c sample.c

同様に、リンク時は "libtool --mode=link" に続けてCコンパイラのコマンド行を 記します。

libtool --mode=link gcc -o sample sample.o -L/usr/local/lib -lidnkit

できあがったコマンドを所定のディレクトリにインストールする際は、 "libtool --mode=install" に続けてinstallコマンドの 実行行を記します。

libtool --mode=install install -m755 sample /usr/local/bin

プログラム例

ここでは、高レベルAPIを使用して国際化ドメイン名の名前解決を行うための、 簡単なプログラムを紹介します。

#include <stddef.h>
#include <sys/types.h>
#include <stdio.h>
#include <locale.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <idn/api.h>

int
main(int ac, char **av) {
  struct hostent *hp;
  char buf1[256];
  char buf2[256];
  char addr[100];
  idn_result_t r;

  /* ロケールを設定する */
  setlocale(LC_ALL, "");
  if (ac != 2) {
    fprintf(stderr, "Usage: %s hostname\n", av[0]);
    return 1;
  }
  /* apiモジュールを初期化する */
  if ((r = idn_nameinit(1)) != idn_success) {
    fprintf(stderr, "idn_nameinit: %s\n", idn_result_tostring(r));
    return 1;
  }
  /* gethostbynameを呼ぶ前に名前を変換する */
  if ((r = idn_encodename(IDN_ENCODE_LOOKUP, av[1],
      buf1, sizeof(buf1))) != idn_success) {
    fprintf(stderr, "idn_encodename: %s\n", idn_result_tostring(r));
    return 1;
  }
  /* 名前解決を行う */
  if ((hp = gethostbyname(buf1)) == NULL) {
    fprintf(stderr, "gethostbyname failed\n");
    return 1;
  }
  /* 返された名前をローカルエンコーディングに変換する */
  if ((r = idn_decodename(IDN_DECODE_LOOKUP, hp->h_name,
      buf2, sizeof(buf2))) != idn_success) {
      fprintf(stderr, "idn_decodename: %s\n", idn_result_tostring(r));
      return 1;
  }
  inet_ntop(hp->h_addrtype, hp->h_addr, addr, sizeof(addr));
  printf("%s %s\n", addr,  buf2);
  return 0;
}

[left] [up] [right]