ライブラリの基礎 - スタティックライブラリの作成(C/C++/MFC)

提供:MochiuWiki : SUSE, EC, PCB
2021年11月24日 (水) 18:07時点におけるWiki (トーク | 投稿記録)による版 (文字列「<source」を「<syntaxhighlight」に置換)
ナビゲーションに移動 検索に移動

概要

スタティックライブラリ(静的ライブラリ)は、ソフトウェアに静的にリンクされるライブラリで、ソフトウェアのビルド時にリンクされる。
ライブラリに含まれる関数は、 実行ファイルに組み込まれるので、DLLのようにファイルをパスの通ったディレクトリ等などに配置する必要はない。

DLLでは、他のソフトウェアとライブラリを共有できるが、
スタティックライブラリでは、実行ファイルにライブラリが組み込まれるので、他のソフトウェアとの共有はできない。

また、DLLでは、実行時にLoadLibrary関数により、公開関数のロードおよび実行ができるが、スタティックライブラリでは、そのようなことはできない。

ここでは、実際に、Visual Studioを使用してスタティックライブラリを作成する。


スタティックライブラリのプロジェクトの作成

Visual Studioを起動して、[新しいプロジェクト]画面で[Windows デスクトップ]を選択して、プロジェクト一覧の中から[スタティックライブラリ]を選択する。
プロジェクトが作成されると、最初はヘッダファイルもソースファイルも存在しないので、プロジェクトを選んで[追加]コンテキストメニューから
ヘッダファイルとソースファイルを追加する。

ここでは、StaticLib.hファイルとStaticLib.cppファイルを追加する。


スタティックラブラリのサンプルコード

以下のサンプルコードは、PC上に接続されているドライブ一覧を取得する関数をスタティックライブラリとして実装したものである。
DLLと違って、スタティックライブラリでは、モジュール定義ファイル(.defファイル)やexport宣言は不要である。
つまり、グローバルな関数は全て公開される。

<syntaxhighlight lang="c++">
// StaticLib.h
// ヘッダファイルでは関数のプロトタイプを宣言する
// このファイルは、stdafx.hにインクルードする必要がある

#pragma once

#include <Windows.h>

extern "C" int GetLogicalDriveCount();
extern "C" BOOL GetLogicalDriveString(int, LPWSTR, int);
</source>


<syntaxhighlight lang="c++">
// StaticLib.cpp
// ソースファイルでは、関数の具体的な実装を記述する

#include "stdafx.h"
#define BUFFSIZE 1024

// 論理ドライブの数を取得する
int GetLogicalDriveCount()
{
   WCHAR buffer[BUFFSIZE];
   DWORD ret = GetLogicalDriveStrings(BUFFSIZE, buffer);

   if (ret == 0 || ret > BUFFSIZE)
       return -1;

   // '\0' の数を数える。
   int c = 0;
   int i = 0;

   while (!(buffer[i] == '\0' && buffer[i + 1] == '\0'))
   {
      if (buffer[i] == '\0')
      {
         c++;
      }

      i++;
      if (i >= BUFFSIZE)
           break;
   }

   c++;

   return c;
}

// 指定された番号(0,1,2,3..)の論理ドライブ名を取得する
BOOL GetLogicalDriveString(int n, LPWSTR drive, int m)
{
   WCHAR buffer[BUFFSIZE];
   DWORD ret = GetLogicalDriveStrings(BUFFSIZE, buffer);

   if (ret == 0 || ret > BUFFSIZE)
   {
      return FALSE;
   }

   lstrcpyn(drive, buffer, m);
   LPCWCHAR p = buffer;
   int c = 0;

   while (c < n)
   {
      while (*p != '\0')
      {
         p++;
      }
      p++;
      lstrcpyn(drive, p, m);
      c++;
   }
   return TRUE;
}
</source>



実行ファイルのサンプルコード

この実行ファイルのサンプルコードでは、スタティックライブラリのGetLogicalDriveCount関数でドライブ数を取得して、
GetLogicalDriveString関数を使用して、具体的なドライブ名を取得して表示する。

StaticLib.hファイルは、スタティックライブラリのプロジェクトからコピーしてプロジェクトに含める。
または、実行ファイルのプロジェクトの[プロパティ] - [C/C++] - [全般] - [追加のインクルードディレクトリ]にStaticLib.hファイルが存在するフォルダを追記する。(この時、画面左上の構成を[すべての構成]にする)

ライブラリファイル((StaticLib.lib)がソリューションのDebugフォルダに出力されているので、そのライブラリファイルを、
実行ファイルのプロジェクトのプロパティの[リンカー] - [入力] - [追加の依存ファイル]に追加する。(これにより、スタティックライブラリがビルド時にリンクされる)
または、実行ファイルのプロジェクトの[プロパティ] - [リンカー] - [全般]にある[追加のライブラリディレクトリ]にStaticLib.libファイルが存在するフォルダを追記する。
続いて、上記と同様に[リンカー] - [入力] - [追加の依存ファイル]に、StaticLib.libと記載する。

実行ファイルのサンプルコードを以下に記述する。

<syntaxhighlight lang="c++">
// ExeStaticLib.cpp : アプリケーションのエントリ ポイントを定義します。

#include "stdafx.h"
#define DRIVELEN 128

int main(int argc, char *argv[])
{
   WCHAR drive[DRIVELEN];

   // ドライブの数を得る。
   int n = GetLogicalDriveCount();
   if (n < 0)
   {
      printf_s("Error.\n");
      getchar();

      return 1;
   }
   else
   {
      printf_s("ドライブの数 = %d\n", n);
   }
   // ドライブ一覧を表示する。
   for (int i = 0; i < n; i++)
   {
      GetLogicalDriveString(i, drive, DRIVELEN);
      wprintf_s(L"%s\n", drive);
   }
   getchar();

   return 0;
}
</source>


このプログラムの実行例を以下に示す。

ドライブの数 = 3
C:\
D:\
E:\