Nodachisoft Nodachi Sword Icon
  
@あまじ✎ 2021年3月12日に更新

第2章63 自作ライブラリDLLを作る

イチからゲーム作りで覚えるC言語
第2章62 文字列を操作する関数 : PREV
NEXT : 第2章64 外部コマンド実行 :

概要

便利機能を集めたライブラリと呼ばれるプログラムを作成していきましょう。

Windows 環境上で、様々な機能をまとめたライブラリを「DLLファイル」という形式で作成することができます。

DLLファイルは、Dynamic Load Library の略で、「動的に読み込みのできるライブラリ」のことです。 DLL を作ることで、こんなメリットがあります。

  • 共通する機能をまとめて、さまざまなアプリから利用可能。いろんなアプリから関数を利用(シェア)できるライブラリなので、シェアードライブラリと呼ばれます。
  • DLL を使う側は C言語でなくても良い。Python 、 VisualBasic 、 C#(.NET) 、Go、などなど、様々な言語から C言語で書いた関数を呼び出しできる。
  • 一部の機能を別の人が担当して役割分担して開発できる。
  • 関数の実際の中身を DLL にして、あとから DLLファイルを入れ替えることで、バージョンアップ可能。

今回は、簡単な機能を DLL ファイルにしてみて、 別のプログラムから DLL の機能を呼び出してみましょう。

関数

簡単なhp計算の関数 calcHitpoint を作成してみます。

 
dll_ex.c
__declspec(dllexport) int __cdecl calcHitpoint( int lv ) {
  return lv * 5;
}

今までになかった、「__declspec(dllexport)」、「__cdecl」 といった属性が関数の宣言に追記されています。

__declspec(dllexport) 属性

DLLにしたときに、利用可能な関数にこの属性を記載します。 もし、DLLの中だけで呼ばれる、関数であれば、記載する必要はありません。

今回は関数 calcHitpoint は DLL にしたとき、別のプログラムから呼出しできるようにしたいので、 「__declspec(dllexport)」を記載しておきます。

declspec の意味

declspec は Declaration of Specification の意味です。

__cdecl 呼出し規約

「__cdecl」は呼出し規約(Calling Convention)と呼ばれるキーワードの一つで、 cdecl は C declaration の略で、つまり C 言語の関数宣言のことを指しています。

この __cdecl を関数の宣言時に記載してあげることで、外部から DLL のこの関数を呼び出すとき、 どんな風に呼び出したらよいのかをコンパイラに教えてあげる役割を果たします。

今回は通常のC言語の作り方で DLL の関数を作成するので、「__cdecl」の呼出し規約を指定しておきます。

呼出し規約

「__cdecl」の他、呼出し規約には 「__stdcall」 などがあります。 Windows 標準の機能を利用するときに、使います。

では、今回のプログラムを DLL にしてみましょう!

コンパイル
gcc -o dll_ex.dll -s -shared dll_ex.c -Wl,--subsystem,windows
  • 「-o」で、ファイル名「dll_ex.dll」にコンパイルした結果(DLLファイル)を出力しています。
  • 「-s」で必要なライブラリをかき集めてコンパイル結果(DLLファイル)にまとめることを指定しています。
  • 「-shared」でシェアードライブラリ(Shared Library)を指定して、DLL形式にすることを指定しています。

特に問題なければ、これで「dll_ex.dll」ファイルが出来上がります!

-Wl,--subsystem,windowsオプション

「-Wl,--subsystem,windows」は Windows 関連の機能を DLL 内で利用するときに リンカに手動で、機能利用を伝えるするためのオプションです。 今回の場合は、 DLL 内の関数では Windows 関連機能を使用していないので、付けなくても問題ありません。

DLL ファイルの利用

出来あがった DLLファイル(dll_ex.dll)を別のプログラムを作成して、呼び出してみましょう。 今回は呼び出す側も C 言語で作成します。

 
usedll_ex.c
#include <stdio.h>
__declspec(dllimport) int __cdecl calcHitpoint(int lv);
int main() {
  printf("%d\n", calcHitpoint(5));
}

2 行目で、呼び出したい関数の宣言を書いてあげます。 関数の実態(定義)は DLL を参照し、DLL の中身が実行されます。

呼ぶ側は「__declspec(dllimport)」と記載している部分がちょっと違いますね。

あとは DLL の中身を定義したときと一緒です。 このソースコードをコンパイルしてみましょう。

コンパイルする際に、ファイル「dll_ex.dll」を利用することを明記します。

コンパイル
gcc usedlll_ex.c -o usedll.exe -L. -ldll_ex
  • 「-o」オプションで実行可能なプログラム「usedll.exe」を作成する指示をします
  • 「-L」オプションでライブラリを読み込むパスを指定します。パスの場所はスペースなどは入れずに指定できます。「-L.」と記載しているので、ライブラリの位置は「.」つまり、同じフォルダにあることを指示しています。
  • 「-l」で読みこっむライブラリ(DLLファイル)の名前を指定します。拡張子「.dll」は省略して記載します。

問題なければ、usedll.exe ファイルが出来上がります。

プログラム実行

出来上がった usedll.exe をコンソールから実行します。

実行結果
> .\usedll.exe
25

ちゃんとcalcHitpoint関数が実行された結果が表示されました。

usedll.exe の中で、 calcHitpoint 関数が呼ばれたときは、 dll_ex.dll ファイルの実際の calcHitpoint 関数が呼び出され実行されます。

ためしに、usedll.exe はそのままにして、 DLLファイルの中身である、 dll_ex.c の計算式部分を下のように書き換えてみます。

 
dll_ex.c
__declspec(dllexport) int __cdecl calcHitpoint( int lv ) {
  return lv * 100;
}

再度 dll_ex.c を DLL ファイルにコンパイルしてから、 usedll.exe を実行すると、 ちゃんと、新しい calcHitpoint 関数が呼び出されて、下のような結果になりました。

実行結果
> .\usedll.exe
500

このように一部の機能を分けることで、 例えば、キャラクタの体力を計算するプログラム開発と、 ゲームエンジンを開発するプログラム開発の担当を分けるなどもできるようになります。

参考文献

イチからゲーム作りで覚えるC言語
第2章62 文字列を操作する関数 : PREV
NEXT : 第2章64 外部コマンド実行 :
 
 
送信しました!

コメント、ありがとうございます。

なんかエラーでした

ごめんなさい。エラーでうまく送信できませんでした。ご迷惑をおかけします。しばらくおいてから再度送信を試していただくか、以下から DM などでご連絡頂ければと思います。

Twitter:@NodachiSoft_jp
お名前:
 
連絡先:
 
メッセージ:
 
戻る
内容の確認!

以下の内容でコメントを送信します。よろしければ、「送信」を押してください。修正する場合は「戻る」を押してください

お名前:
 
連絡先:
 
メッセージ:
 
Roboto からの操作ではないという確認のため確認キーを入れてください。
確認キー=95
戻る
 / 
送信確認へ
コメント欄
コメント送信確認へ

関連ありそうな記事(5件)です!

第1章01 Visual Studio Community 2019 のインストール手順

#C11仕様#C言語#ゲームプログラミング✎ 2021-08-08
C言語でプログラミングをするために、無料で使える Visual Studio Community を使った開発環境を揃えていく手順や注意点をお話しています。
目次
第2章63 自作ライブラリDLLを作る
第2章63 自作ライブラリDLLを作る
概要
概要
関数
関数
\_\_declspec(dllexport) 属性
\_\_declspec(dllexport) 属性
\_\_cdecl 呼出し規約
\_\_cdecl 呼出し規約
DLL ファイルの利用
DLL ファイルの利用
プログラム実行
プログラム実行
参考文献
参考文献
Nodachisoft © 2021