MSYSとMinGWでGSLをビルドしてVisual C++から使う

出典: Wikimura

数値計算ライブラリGSLの古いバージョン(1.10)にバグがあったため、最新版を入手することにした。 GSLはWindowsでも動くが、VisualStudioでビルドするには工夫が必要らしい。 1.8や1.10についてはVisualStudioのプロジェクトやバイナリが配布されているが、どうせなら最新版を常に手に入れられるようにしたい。そこで、GSLのビルド方法について調べた。

この方法では呼び出し規約の違いで不具合が生じるようです。現在調査中... Visual C++でビルドすることで解決しました。方法をGSLをVisualC++でビルドする に書きました。

目次

注意! このページの内容は間違っています。正しくは「GSLをVisualC++でビルドする」の方を参照してください

このページの通りにやるとビルドはできますが、gccとcl(Visual C++のコンパイラ)で呼び出し規約に違いがあるため、ランタイムエラーを起こします。

最初からVisual C++を使ってビルドすれば解決します。GSLをVisualC++でビルドするを参照してください。

エラーが起こる例:

#include <gsl/gsl_vector.h>
#include <stdio.h>

int main( void)
{
	double array[3] = { 1, 2, 3};
	gsl_vector_view view = gsl_vector_view_array( array, 3);
	return 0;
}

エラーメッセージ:

Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. 
This is usually a result of calling a function declared with one calling convention with
a function pointer declared with a different calling convention.

必要なものは

詳しくは[6][7]参照。MinGWをインストール後、MSYSをインストールし、環境変数を設定する。

Unix模擬環境(Cygwin or MSYS)

GSLはUnix向けのライブラリらしく、UNIXが提供する機能(システムコール?)を必要とするらしい。 そのため、Windows上でUnix環境を模擬するソフトウェアが必要となる。 これにはCygwinかMSYSを用いることができるらしい。

始めはCygwinを使おうと考えたが、Cygwinではホスト(コンパイルしたものを実行する側)がi686-pc-cygwinのgccに都合よく設定されているので、結構面倒なことが分かった。

ここは素直にMSYSを使うことにした。 MSYSのインストールについては[7]参照。

MinGW

gccのWindows移植版で、直接Windows上で動くプログラムを作るためのツールチェインとのこと。 (Cygwinなどのgccでは、そのままではWindows上で動くことができず、cygwin.dllが必要とか言われてしまう)


ビルドする

MSYSのコンソールを立ち上げ、GSLのソースディレクトリへ移動する。 (Cygwinと異なり、ドライブはルート直下にマウントされている)

./configure --prefix インストール先
make
make check
make install

設定項目は configureで -h オプションを使えば調べられる。prefixでインストール先を指定する以外、特にやることはなかった。 何事もなくビルドでき、checkも問題なく実行できた。 特に指定しなければ、静的ライブラリと動的ライブラリの両方が生成される。

1.13では、前に書いたgsl-1.10での「 subrow/subcolumnのバグ」は解決されていた。


Visual Studioからの利用方法

ビルドしたGSLをVisual Studio(というかC++)から利用するには、以下の設定を行う。 GSL_DirはGSLをインストールしたディレクトリ。configure時に--prefixオプションで指定した場所。

Visual Studio側の設定: 全てのプロジェクトに適用されるので便利(個別のプロジェクトで設定することもできる)

  • ツール -> オプション -> プロジェクトおよびソリューション -> VC++ディレクトリ
    • インクルードファイル: (GSL_Dir)/include
    • ライブラリファイル: (GSL_Dir)/lib
    • 実行可能ファイル: (GSL_Dir)/bin -> デバッグ時にDLLが探せるようになる

個別プロジェクトでの設定: Visual Studio側でディレクトリ設定がされていない場合、こちらで設定する。

  1. DLLで利用する場合:
    • 構成プロパティ
      • リンカ -> 入力 -> 追加の依存ファイル: libgsl.dll.a libgslcblas.dll.a
      • C/C++ -> プリプロセッサ -> プリプロセッサの定義: (既存のシンボル定義);GSL_DLL(区切り文字としてセミコロンを使う)
  2. 静的ライブラリで使用する場合:
    • 構成プロパティ
      • リンカ -> 入力 -> 追加の依存ファイル: libgsl.a libgslcblas.a

うまくいかない?

MinGWでコンパイルすれば呼び出し規約(calling convention)がVisualStudioに合わせてもらえるものと思い込んでいたが...違うらしい。 gsl_vector_view_array関数をある関数内で実行したところ、関数から抜け出す際に、スタックがおかしいと怒られるという現象に遭遇してしまった。 非常に恥ずかしいミス。エラーメッセージは以下の通り。

Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call.  This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.

[1]に以下のような気になる記述があった。

Visual C++を利用する理由: 構築したライブラリをVisual C++から利用するためです. Windows上で開発をする以上,準公式のVisual C++で行うのが好ましいと言えます. また,MinGWのdllwrapで構築されるインポートライブラリは Visual C++のものと互換性が無いようです.

更に、

以上の事情から,このページで作ったDLLはVisual Basicその他から利用することは出来ないと思われます.この場合はVisual C++で__stdcallを利用したラッパーライブラリを書くなどして対処してください.著者個人の見解では「実装上の問題が山積している状況でVBなど使うな」ということになるのですが.

とのこと。ライブラリやDLLが目の前に現れたからといって、そのまま使えるとは限らないということらしい。(昔H8でHEWのライブラリをGCCから使ってやろうとして痛い目にあったことがあるのに、またやってしまった


現在調査中。

参考文献・ソフトウェア

  1. GSL本家
  2. 古いバージョンのGSLのバグ
  3. GSL日本語マニュアル
  4. MSYS本家
  5. Cygwin本家
  6. MinGWで使うgsl (Windowsでのフリーソフトによる数値計算環境の構築)
  7. MinGW+MSYSのインストール方法
  8. MinGW(Wikipedia)
  9. MSYS(Wikipedia)
個人用ツール