『【1/3】DLLを作成してみる』で作成したDLLを利用するアプリケーションを書いてみる。
繰り返しになりますが、想定しているのは以下のプラットフォーム(開発環境)です。
今回も、単一のC言語ソースで、複数アーキテクチャ向けのアプリケーションとしてビルドします。
DLLを利用する方法は、大きく分けて2種類あります。
リンカ実行時にDLLのシンボルを紐づけておく「動的リンク(ダイナミックリンク)」と、ビルド時にはシンボルは未解決のままにしておいて実行時にDLLを明示的にロードする「動的ロード(ダイナミックロード)」です。
今回は「動的リンク」を使ったアプリケーションを作成してみます。
なお、前回作成した、DLLのファイル,ソースコードは、『../simple_dll』というディレクトリに置いてあるものとします。
「動的ロード」を使ったアプリケーションは次回の記事を参照して下さい。
【2/3】DLLを使ってみる(動的リンク版)
目次
ソースコード
[dllUser_DynamicLink.c]
/****************************************************************//**
* \file dllUser_DynamicLink.c
*
* \brief DLL(ダイナミックリンクライブラリ)を実行時にリンクするサンプルアプリケーション
*
* - 文字コード・改行コード
* - 文字コードは UTF-8(BOM無し)
* - 改行コードは LF
*
* \author tomyama Sep 2022
********************************************************************/
/********************************************************************/
/* include files */
/********************************************************************/#include <stdio.h> // puts()
#include "simple_dll.h"
/********************************************************************/
/* defines */
/********************************************************************/
/********************************************************************/
/* types */
/********************************************************************/
/********************************************************************/
/* function prototype (static) */
/********************************************************************/
/********************************************************************/
/* static value */
/********************************************************************/
/********************************************************************/
/* globals variable */
/********************************************************************/
/********************************************************************/
/* function (global) */
/********************************************************************//********************************************//**
* \brief プログラムのエントリポイント。
*
* \param[in] argc 引数の数。
* \param[in] argv 引数ポインタの配列。
* \return プログラムの終了ステータスを返す。
* \retval 0 正常終了(常に 正常終了 を返す)
* \author tomyama
* \sa -
* \callgraph
* \callergraph
************************************************/int main( void )
{
puts( getGreetingMsg() );return 0;
}
/********************************************************************/
/* function (static) */
/********************************************************************/
Windows環境向けにビルドして実行する手順
- スタートメニューからVisual Studioの『x86 Native Tools Command Prompt for VS 20xx』を起動する。
- 以下のバッチファイルを作成して実行する。
-
[build_and_run_DynLink.bat]
set LIBDIR=../simple_dll
set CFLAGS=/nologo /source-charset:utf-8 /execution-charset:shift_jis /Wall /wd4464 /wd4668 /wd4710 /wd4820 /wd4996 /wd5045 /O2 /Ob0rem 動的リンク [ Dynamic Link ]
rem ビルド
cl.exe %CFLAGS% /I%LIBDIR% /Fo:dllUser_DynamicLink_msvc.o /c dllUser_DynamicLink.c
link.exe /OUT:dllUser_DynamicLink_msvc.exe dllUser_DynamicLink_msvc.o %LIBDIR%/simple_dll_msvc.lib
rem 実行
echo off
set PATH_ORG=%PATH%
set PATH=%LIBDIR%;%PATH%
echo on
dllUser_DynamicLink_msvc.exe
echo off
set PATH=%PATH_ORG%
set PATH_ORG=
echo on
-
- 実行結果は以下のようになるはずです。赤字箇所がDLLの関数を呼び出した所です。
-
user_app_DynLink>build_and_run_DynLink.bat
user_app_DynLink>set LIBDIR=../simple_dll
user_app_DynLink>set CFLAGS=/nologo /source-charset:utf-8 /execution-charset:shift_jis /Wall /wd4464 /wd4668 /wd4710 /wd4820 /wd4996 /wd5045 /O2 /Ob0
user_app_DynLink>rem 動的リンク [ Dynamic Link ]
user_app_DynLink>rem ビルド
user_app_DynLink>cl.exe /nologo /source-charset:utf-8 /execution-charset:shift_jis /Wall /wd4464 /wd4668 /wd4710 /wd4820 /wd4996 /wd5045 /O2 /Ob0 /I../simple_dll /Fo:dllUser_DynamicLink_msvc.o /c dllUser_DynamicLink.c
dllUser_DynamicLink.cuser_app_DynLink>link.exe /OUT:dllUser_DynamicLink_msvc.exe dllUser_DynamicLink_msvc.o ../simple_dll/simple_dll_msvc.lib
Microsoft (R) Incremental Linker Version 14.32.31332.0
Copyright (C) Microsoft Corporation. All rights reserved.
user_app_DynLink>rem 実行user_app_DynLink>echo off
user_app_DynLink>dllUser_DynamicLink_msvc.exe
Hello, world!user_app_DynLink>echo off
user_app_DynLink>
-
Windows以外の環境向けにビルドして実行する手順
- 適当な端末エミュレータを起動する。
- 以下のスクリプトを作成して実行する。
-
[build_and_run_DynLink.sh]
#!/bin/sh
LIBDIR=../simple_dll
CFLAGS="-Wall -O2"arch=`uname -mos | tr ' ./' '_'`
echo "$arch"gcc $CFLAGS -I${LIBDIR} -o dllUser_DynamicLink_${arch}.o -c dllUser_DynamicLink.c
gcc -o dllUser_DynamicLink_${arch}.exe dllUser_DynamicLink_${arch}.o -lsimple_dll_${arch} -L${LIBDIR}if [ "`uname -o`" = "Cygwin" ]; then
PATH=${LIBDIR}:$PATH ./dllUser_DynamicLink_${arch}.exe
else
LD_LIBRARY_PATH=${LIBDIR} ./dllUser_DynamicLink_${arch}.exe
fi
-
- 実行結果は以下のようになるはずです。赤字箇所がDLLの関数を呼び出した所です。
解説
入力ファイル
プラットフォーム(開発環境) | ファイル |
---|---|
WindowsのDLLファイル(Visual Studio) | dllUser_DynamicLink.c |
LinuxのSOファイル(gcc) | |
CygwinのDLLファイル(gcc) | |
Android(Termux)のSOファイル(clang) |
ビルドと実行の台本(スクリプト)
プラットフォーム(開発環境) | ファイル |
---|---|
WindowsのDLLファイル(Visual Studio) | build_and_run_DynLink.bat |
LinuxのSOファイル(gcc) | build_and_run_DynLink.sh |
CygwinのDLLファイル(gcc) | |
Android(Termux)のSOファイル(clang) |
- Cygwinの無い環境でもビルドできるように「Visual Studio」の場合は .bat ファイルにしている。その他の環境ではシェルスクリプト。
- clangの場合は、gccでは無くclangを呼び出す方がより厳密的だが、clangはgccに擬態してくれるように作られているので(少なくとも現時点では)、それに頼ってscriptingしている。
中間生成物: 『dllUser_DynamicLink.c』のコンパイル | |
プラットフォーム(開発環境) | コマンド |
---|---|
WindowsのDLLファイル(Visual Studio) | cl.exe %CFLAGS% /I../simple_dll /Fo:dllUser_DynamicLink_msvc.o /c dllUser_DynamicLink.c |
LinuxのSOファイル(gcc) | gcc -Wall -O2 -I../simple_dll -o dllUser_DynamicLink_${arch}.o -c dllUser_DynamicLink.c |
CygwinのDLLファイル(gcc) | gcc -Wall -O2 -I../simple_dll -o dllUser_DynamicLink_${arch}.o -c dllUser_DynamicLink.c |
Android(Termux)のSOファイル(clang) | gcc -Wall -O2 -I../simple_dll -o dllUser_DynamicLink_${arch}.o -c dllUser_DynamicLink.c |
- 呼び出すコマンドやオプションスイッチに差異はあるものの、必要な要素(コマンドライン引数)は全プラットフォームで同じ。
- ソースコードの中で『simple_dll.h』をインクルードしているので、コンパイラのオプションスイッチ(/I, または -I)で、インクルードパスを追加している。
最終生成物(実行ファイル): リンカで実行ファイルを生成 | |
プラットフォーム(開発環境) | コマンド |
---|---|
WindowsのDLLファイル(Visual Studio) | link.exe /OUT:dllUser_DynamicLink_msvc.exe dllUser_DynamicLink_msvc.o ../simple_dll/simple_dll_msvc.lib |
LinuxのSOファイル(gcc) | gcc -o dllUser_DynamicLink_${arch}.exe dllUser_DynamicLink_${arch}.o -lsimple_dll_${arch} -L../simple_dll |
CygwinのDLLファイル(gcc) | gcc -o dllUser_DynamicLink_${arch}.exe dllUser_DynamicLink_${arch}.o -lsimple_dll_${arch} -L../simple_dll |
Android(Termux)のSOファイル(clang) | gcc -o dllUser_DynamicLink_${arch}.exe dllUser_DynamicLink_${arch}.o -lsimple_dll_${arch} -L../simple_dll |
- Windowsでは、DLLのエクスポートした関数を呼び出す部品(LIBファイル)をリンカで組み込む。
- その他のプラットフォームではDLLを直接参照してシンボルを解決する。その為、DLLの場所と名前をオプションスイッチで指示している。
実行: 『dllUser_DynamicLink_${arch}.exe』を実行 | |
プラットフォーム(開発環境) | コマンド |
---|---|
WindowsのDLLファイル(Visual Studio) | set PATH_ORG=%PATH% set PATH=../simple_dll;%PATH% dllUser_DynamicLink_msvc.exe set PATH=%PATH_ORG% set PATH_ORG= |
LinuxのSOファイル(gcc) | LD_LIBRARY_PATH=../simple_dll ./dllUser_DynamicLink_${arch}.exe |
CygwinのDLLファイル(gcc) | PATH=../simple_dll:$PATH ./dllUser_DynamicLink_${arch}.exe |
Android(Termux)のSOファイル(clang) | LD_LIBRARY_PATH=../simple_dll ./dllUser_DynamicLink_${arch}.exe |
- Windows, Cygwinは環境変数『PATH』を使ってDLLの場所を指示している。
- その他のプラットフォームでは環境変数『LD_LIBRARY_PATH』を使っている。このblogの制約で2行になっているように見えるかもしれないが、環境変数の設定と実行ファイルの実行は、1行で記述すること。シェルは、このように書く事で実行時のみ環境変数を変更してくれる。
- 【1/3】DLLを作成してみる
- 【2/3】DLLを使ってみる(動的リンク版)
- 【3/3】DLLを使ってみる(動的ロード版)