Visual Studio 2017 Visual C++ による Win32 スタティックライブラリの開発


はじめに

スタティックライブラリは、アプリケーションに静的にリンクされるライブラリで、アプリケーションのビルドのときにリンクされます。ライブラリに含まれる関数は exe ファイルに組み込まれるので、DLL のようにファイルをパスの通ったフォルダなどに配置しておく必要はありません。

DLL の場合は、他のアプリケーションとライブラリを共有できますが、スタティックライブラリでは、exe ファイルにライブラリが組み入れられるので、他のアプリケーションとの共有はできません。

DLL の場合は、実行時に LoadLibrary API 関数などにより、公開関数のロード/実行が可能ですが、スタティックライブラリでは、そのようなことはできません。

プロジェクトの作成

「新しいプロジェクト」ダイアログで「Windows デスクトップ」を選び、プロジェクト一覧の中から「スタティックライブラリ」を選んで OK ボタンをクリックします。

プロジェクトが作成されると、最初はヘッダーファイルもソースファイルも入ってないので、プロジェクトを選んで「追加」コンテキストメニューからヘッダーとソースファイルを追加します。下の例では、StaticLib1.h と StaticLib1.cpp を追加しました。

サンプル

このサンプルは、現在のマシン上に接続されているドライブ一覧を取得する関数をスタティックライブラリとして実装したものです。

DLL と違ってスタティックライブラリでは、モジュール定義ファイルや export 宣言などのようなものは不要です。グローバルな関数はすべて公開されます。

StaticLib1.h

ヘッダーファイルでは関数のプロトタイプを宣言します。このファイルは、stdafx.h にインクルードしておく必要があります。

#pragma once

#include <Windows.h>

extern "C" int GetLogicalDriveCount();
extern "C" BOOL GetLogicalDriveString(int, LPWSTR, int);

StaticLib1.cpp

C++ ソースファイルでは、関数の具体的な実装を記述します。

#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;
}

テストプログラム

このテストプログラムでは、ライブラリ関数 GetLogicalDriveCount でドライブ数を取得して、GetLogicalDriveString 関数を使って、具体的なドライブ名を取得して表示しています。

StaticLib1.h はスタティックライブラリ・プロジェクトからコピーしてプロジェクトに含めます。このヘッダーは stdahx.h にインクルードしておく必要があります。

ライブラリファイル (StaticLib1.lib) がソリューションの Debug フォルダにできているはずなので、それをプロジェクトのプロパティの「リンカー」「入力」の「追加の依存ファイル」に追加しておきます。(これによりスタティックライブラリがビルド時にリンクされる)

テストプログラムソースを下に示します。

// TestStaticLib1.cpp : アプリケーションのエントリ ポイントを定義します。
//
#include "stdafx.h"
#define DRIVELEN 128

int main()
{
    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;
}

下のイメージはこのテストプログラムの実行例です。

-