mieki256's diary



2023/12/01(金) [n年前の日記]

#1 [prog][windows] FreeImageライブラリをMinGWで使ってみたい

C/C++から利用できる、画像読み込みをしてくれる FreeImage というライブラリがある。

_The FreeImage Project

Windows10 x64 22H2 + MSYS2 + MinGW64 上であれば、FreeImage のパッケージが用意されているので、該当パッケージをインストールするだけで利用できるようになる。そのことについては以前試した。

_mieki256's diary - FreeImageとDevILライブラリを試用

これを、MinGW (g++ 9.2.0) から利用してみたいと思い立った。環境は Windows10 x64 22H2。

ファイルを入手 :

_The FreeImage Project

公式サイトから、以下の2つを入手。バージョンは FreeImage 3.18.0。2018/08/01頃に公開された版らしい。
  • FreeImage3180.zip : ソースファイル群
  • FreeImage3180Win32Win64.zip : VisualC++用のライブラリファイル(バイナリ)

MinGW用ライブラリファイルに変換 :

FreeImage3180Win32Win64.zip を解凍してみたところ、README.minGW というテキストファイルがあった。その中で、MinGW用ライブラリファイル、libfreeimage.a への変換方法が書いてあった。FreeImage.dll の中にある関数名をリストアップして、その関数を呼ぶライブラリファイルになるらしい。いわゆる動的リンク、というヤツだろうか。

解凍して得られたフォルダ内の、Dist\x32\ に移動して作業。
pexports FreeImage.dll | sed "s/^_//" > libfreeimage.def
dlltool --add-underscore -d libfreeimage.def -l libfreeimage.a
  • pexports を使って、dll内の関数名の一覧を libfreeimage.def に書き込む。
  • dlltool を使って、ライブラリファイル libfreeimage.a を作成する。
  • pexports は、自分の環境では、何故か Strawberry Perl 5.32.0.1 x64 のインストールフォルダの中にあった。調べてみたら、本来は MinGW Installer 経由でインストールできるようだなと…。パッケージが用意されてた。
  • dlltool は、Mingwインストールフォルダ\bin\ の中にあった。

とりあえず、これで、libfreeimage.a が生成できた。各ファイルを以下の場所にコピーしておく。
  • libfreeimage.a を、MinGWインストールフォルダ\lib\ にコピー。
  • FreeImage.dll を、MinGWインストールフォルダ\bin\ にコピー。
加えて、 FreeImage.h を、以下のフォルダにコピー。
  • MinGWインストールフォルダ\include\
  • MinGWインストールフォルダ\lib\gcc\mingw32\9.2.0\include\c++\

余談。ググってたら、pexports について、この日記にもメモしてあった…。完全に記憶の中から無くなっていた…。

_mieki256's diary - dllからMinGW用のライブラリファイルを作成

FreeImageを使うファイルをビルド :

FreeImage を使うプログラムをビルドしたい時は、以下のように -lfreeimage を指定すればいいらしい。
g++ -static 01_load_png01.cpp -o 01_load_png01.exe -lfreeimage

ちなみに、上記の指定では、-static を付けているので、極力静的リンクをしてくれるらしい。ただ、前述のように、FreeImage.dll は動的リンクなので、出来上がった exe を実行するには、別途 FreeImage.dll が必要になる。

stdlib.h が見つからないというエラーが出た :

以前、 _MSYS2 + MinGW64用に書いたサンプル を MinGW でビルドしようとしたら、fatal error: stdlib.h: No such file or directory というエラーが出た。

includeパス(ヘッダーファイル群が入ってる場所)を指定する環境変数がおかしかったらしい…。以下のように環境変数を設定したらエラーが出ずにビルドが通るようになった。
CPLUS_INCLUDE_PATH=(MinGWインストールフォルダ)\lib\gcc\mingw32\9.2.0\include\c++

ちなみに、元々は以下のように指定していた。
CPLUS_INCLUDE_PATH=(MinGWインストールフォルダ)\include

関連情報を調べたところ、CPATH という環境変数で、C/C++共通のヘッダファイルの場所を指定できるらしい。合ってるのかどうかわからんけど、とりあえず以下のような指定をしておいた。
set MINGW_PATH=(MinGWインストールフォルダ)

set CPATH=%MINGW_PATH%\include
set C_INCLUDE_PATH=%MINGW_PATH%\include
set CPLUS_INCLUDE_PATH=%MINGW_PATH%\lib\gcc\mingw32\9.2.0\include\c++

FreeImage を静的リンクできない :

生成されたexeファイルが要求してくる dll を調べたら以下のようになった。
> objdump -p 01_load_png01.exe | grep -e "DLL Name"
        DLL Name: FreeImage.dll
        DLL Name: KERNEL32.dll
        DLL Name: msvcrt.dll
        DLL Name: msvcrt.dll

.exe とは別に、FreeImage.dll が必要な状態。いわゆる動的リンク。コンパイル済みの FreeImage バイナリを利用する分には、こういう状態になる。

どうせなら静的リンクをしたい。README.minGW を眺めたら、「静的リンクができる FreeImage (libfreeimage.a) は、環境変数 FREEIMAGE_LIBRARY_TYPE を STATIC に変更してビルドすれば作れる」と書いてあった。試しにビルドしてみる。

FreeImage3180.zip を解凍。

Makefile.mingw の、18行目のコメントアウトを外すように修正。
#FREEIMAGE_LIBRARY_TYPE = STATIC
↓
FREEIMAGE_LIBRARY_TYPE = STATIC

以下を実行。
make -f Makefile.mingw

あるいは、Makefile の最初のあたりの、MAKEFILE = gnu という指定を、mingw に書き変えて、その状態で make とだけ打っても良い。
MAKEFILE = gnu
↓
MAKEFILE = mingw

Dist\ の中に以下の2ファイルが生成された。
  • FreeImage.h
  • libFreeImage.a

それぞれ、以下の場所にコピーする。
  • libfreeimage.a を、(MinGWインストールフォルダ)\lib\ にコピー。
  • FreeImage.h を、(MinGWインストールフォルダ)\include\ にコピー。
  • FreeImage.h を、(MinGWインストールフォルダ)\lib\gcc\mingw32\9.2.0\include\c++\ にコピー。

しかし、このファイルを使ってビルドすると、ld.exe (リンカ)がエラーを出してしまう…。
> g++ 01_load_png01.cpp -o 01_load_png01.exe -lfreeimage -static
d:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: C:\Users\xxxxxxxxx\AppData\Local\Temp\ccmw2cGP.o:01_load_png01.cpp:(.text+0x3e): undefined reference to `_imp__FreeImage_Initialise@4'
d:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: C:\Users\xxxxxxxxx\AppData\Local\Temp\ccmw2cGP.o:01_load_png01.cpp:(.text+0x48): undefined reference to `_imp__FreeImage_GetVersion@0'
d:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: C:\Users\xxxxxxxxx\AppData\Local\Temp\ccmw2cGP.o:01_load_png01.cpp:(.text+0x5f): undefined reference to `_imp__FreeImage_GetCopyrightMessage@0'
...

_c++ - Fail to static linking FreeImage 3.15.4 on MingW - Stack Overflow

以前は FreeImage 3.15.4 で成功したという話を見かけたので、3.15.4 や 3.17.0 (FreeImage3154.zip, FreeImage3170.zip) を入手して試してみたけれど、3.15.4 も 3.17.0 もビルドの途中でエラーが出てしまう…。3.18.0 ならビルドだけは通るのだけど…。


_FreeImage / Discussion / Help: MinGW compiling errors
_FAQ - The FreeImage Project

FAQページに、静的リンクは難しいぞ、と書いてあるように見える…。基本的に、dll が別にあることを前提に作られているっぽい。
  • 最初に FreeImage_Initialise() を呼んで、最後に FreeImage_DeInitialise() を呼べ、とか。
  • #define FREEIMAGE_LIB を追加せよ、とか。
  • あるいはリンカに、-DFREEIMAGE_LIB を追加したり、-lwsock32 -lws2_32 も追加せよ、とか。

色々試してたら、静的リンクができた、かもしれない。以下の指定でリンカがエラーを出さなくなったし、生成された .exe もそれらしく動いてくれた。
g++ 01_load_png01.cpp -DFREEIMAGE_LIB -static -lfreeimage -lwsock32 -lws2_32 -o 01_load_png01.exe

要求される dll を調べてみる。
> objdump -p 01_load_png01.exe | grep -e "DLL Name"
        DLL Name: KERNEL32.dll
        DLL Name: msvcrt.dll
        DLL Name: msvcrt.dll
        DLL Name: WSOCK32.DLL

freeimage.dll の名前が出てこなくなった。

生成された .exe も、freeimage.dll を使う版は 2.2MBだったけど、静的リンクをしたら 8.9MB になった。今までよりサイズが大きくなったので、静的リンクされているのだろう。たぶん。

でもまあ、dll を使って動作するようにしておくか…。元々、動的リンクで使うことを前提にしてあるライブラリのようだし…。

以上です。

過去ログ表示

Prev - 2023/12 - Next
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 27 28 29 30
31

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project