概要

DLLロードの仕方には、静的リンク(暗黙的)と動的リンクがあります。
静的リンクの場合は、LIBファイルが必要となりますが、例えば文字コードの変換を行うMLANG.DLL等は、ヘッダーファイルは存在しますが、なぜかMLANG.LIBは存在しません。
LIBファイルがない場合は、DLLファイルからDEFファイルを作成し、DEFファイルをもとにLIB.EXEによりLIBファイルを作成することができます。
ただし、extern "C" _stdcallで定義されている関数の場合、 DEFファイルのみでLIB.EXEを使用して作成すると32bitの場合コンパイラの名前修飾規則とLIB.EXEの名前検索方法の指定が一致しないためリンクエラーか実行時にエラーが発生します。(Windows 64bitでは__stdcallは無視されるのでLIB.EXEのみで正常なLIBファイルを作成可能)

32bitで正常に動作する場合の各関数名及びエクスポート名

呼び出し側のconvstr2.cppのプロトタイプ宣言

extern "C" HRESULT __stdcall ConvertINetMultiByteToUnicode(LPDWORD , DWORD , LPCSTR , LPINT , LPWSTR ,  LPINT ); 

呼び出し側のmlang.objファイルの呼び出し名

_ConvertINetMultiByteToUnicode@24
__stdcallを宣言することにより先頭に_末尾に@24がコンパイラにより付加される。

呼び出されるmalng.dll内のエクスポート名

ConvertINetMultiByteToUnicode

リンク時に指定するmlang.libファイルのエクスポート名

_ConvertINetMultiByteToUnicode@24
libファイル内で先頭の_と末尾の@24を無視する方法が指定されているのでリンク及び実行時にエラーが発生しない。 ここでは、Windows APIをDEFファイルとソースファイルを作成し、LIBファイルを作る方法を記載し 実際にmlang.dllからmlang.libを作成しConvertINetMultiByteToUnicode APIを呼び出す例を次項以降で示します。

64bitでのLIBファイルの作成

64bitでのコンパイルでは__stdcallが無視されるため、extern "C"により名前の修飾が行われません。 64bitのmlang.dllからmlang.libを作成する場合は、以降で説明する面倒な方法を用いずLIB.EXEを用いて以下のようにVisual C++のコマンドプロンプトで以下の様に入力すれば作成できます。
lib /def:mlang.def /machine:x64

呼び出し側のconvstr2.cppのプロトタイプ宣言

extern "C" HRESULT __stdcall ConvertINetMultiByteToUnicode(LPDWORD , DWORD , LPCSTR , LPINT , LPWSTR ,  LPINT );

呼び出し側のmlang.objファイルの呼び出し名

ConvertINetMultiByteToUnicode
__stdcallが無視されるので、関数名と同一。

呼び出されるmalng.dll内のエクスポート名

ConvertINetMultiByteToUnicode

リンク時に指定するmlang.libファイルのエクスポート名

ConvertINetMultiByteToUnicode

注意点

なお、LIBファイルを作成及び呼び出し側のVisual C++は同じバージョンでしかもビット数は同じでなければなりません。

テスト環境

コンパイラ

Visual C++ 2008 Standard 32/64bit
Visual C++ 2013 Express 32/64bit

プロジェクトの作成

Win32プロジェクト Windowsコンソロールアプリケーション

実行環境

Windows 8.1 Enterprise 64bit
Windows 7 EnterPrise Service Pack 1 64bit
Windows Vista Ultimate Service Pack 2 32bit
Windows XP Professional Service Pack 3 32bit

DLLファイルからLIBファイルを作成する方法

LIBファイルを作成するには、最初にDEFファイルを作成する必要があります。
DEFファイルは、DLLのうち公開する関数名の一覧を記述したファイルです。

DLLファイルからDEFファイルを作成する標準的な方法

LIBファイルのエクスポートしている関数名の一覧を取得するためにdumpbin.exeを使用します。
dumpbin.exeはVisual C++をインストールしたフォルダーの中に存在します。単純にこのファイルをコピーしてもだめで、実行に各種のDLLが必要です。
PATHにdumpbin.exeへのパスを記述するか、スタートメニューのVisual C++のコマンドプロンプトを実行する必要があります。
ここではVisual C++のコマンドプロンプトを使用します。
DEFファイルの作成もとのDLLがD:¥mlang.dll、作成するDEFファイルの名前がD:¥mlang.defの場合の DEFファイルの作成方法は以下の通りです。
スタートメニューからVisual C++のコマンドプロンプトを実行する。
コマンドプロンプトでカレントドライブをD:に移動する。
カレントフォルダーがD:¥でなければCDコマンドによりD:¥にする。
dumpbin /exports D:¥mlang.dllを実行して、関数名が表示されるか確認する。
関数の一覧は、例えば以下のように出力されます。
Microsoft (R) COFF/PE Dumper Version 12.00.31101.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file mlang.dll

File Type: DLL

  Section contains the following exports for MLANG.dll

    00000000 characteristics
    4A5BC5CE time date stamp Tue Jul 14 08:39:58 2009
        0.00 version
         110 ordinal base
          14 number of functions
          12 number of names

    ordinal hint RVA      name

        113    0 000131A2 ConvertINetMultiByteToUnicode
        114    1 0000FAA2 ConvertINetReset
        111    2 00013176 ConvertINetString
        112    3 0000414B ConvertINetUnicodeToMultiByte
        115    4 00001D86 DllCanUnloadNow
        116    5 00002071 DllGetClassObject
        117    6 0001AD5C GetGlobalFontLinkObject
        110    7 0000A613 IsConvertINetStringAvailable
        120    8 0001AE39 LcidToRfc1766A
        121    9 000038EF LcidToRfc1766W
        122    A 0001ADCF Rfc1766ToLcidA
        123    B 00003EC4 Rfc1766ToLcidW

  Summary

        5000 .data
        2000 .reloc
        8000 .rsrc
       1E000 .text
正常に表示されれば、出力をリダイレクトしてd:¥mlang.txtファイルに保存する。
d:¥mlang.txtを開くとDLL内の全部の関数名が一覧されているのでLIBファイルに含めたいファイル名のみを取り出し、以下のように編集してd:¥mlang.defファイルとして保存する。
ここではConvertINetMultiByteToUnicodeだけ抽出して以下のように記述します。
LIBRARY mlang
EXPORTS
 ConvertINetMultiByteToUnicode
大量に関数名を使用したい場合、矩形で選択できるテキストエディタを使用するか、Excelで区切り文字を指定して読み込む方法があります。
以上でdefファイルの作成ができます。
コマンドプロンプトでの入力例を以下に示します。
C:¥Program Files (x86)¥Microsoft Visual Studio 12.0¥VC>d:

D:¥>dumpbin /exports mlang.dll
Microsoft (R) COFF/PE Dumper Version 12.00.31101.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file mlang.dll

File Type: DLL

  Section contains the following exports for MLANG.dll

    00000000 characteristics
    4A5BC5CE time date stamp Tue Jul 14 08:39:58 2009
        0.00 version
         110 ordinal base
          14 number of functions
          12 number of names

    ordinal hint RVA      name

        113    0 000131A2 ConvertINetMultiByteToUnicode
        114    1 0000FAA2 ConvertINetReset
        111    2 00013176 ConvertINetString
        112    3 0000414B ConvertINetUnicodeToMultiByte
        115    4 00001D86 DllCanUnloadNow
        116    5 00002071 DllGetClassObject
        117    6 0001AD5C GetGlobalFontLinkObject
        110    7 0000A613 IsConvertINetStringAvailable
        120    8 0001AE39 LcidToRfc1766A
        121    9 000038EF LcidToRfc1766W
        122    A 0001ADCF Rfc1766ToLcidA
        123    B 00003EC4 Rfc1766ToLcidW

  Summary

        5000 .data
        2000 .reloc
        8000 .rsrc
       1E000 .text

D:¥>dumpbin /exports mlang.dll > mlang.txt

LIB.EXEでdefファイルのみでLIBファイルを作成した場合

defファイルのみから以下のようにコマンド入力するとLIBファイルが作成できます。
lib /def:mlang.def
malng.hの定義を使用した場合の呼び出し名はビルド結果より_ConvertINetMultiByteToUnicode@24となっている。
以下にビルド結果を示します。
convstr.obj : error LNK2001: 外部シンボル "_ConvertINetMultiByteToUnicode@24" は未解決です。
     1>D:¥convstr¥Release¥convstr.exe : fatal error LNK1120: 1 件の未解決の外部参照
LIBファイルのエクスポート名を確認すると以下のようになっている。
D:¥>dumpbin /exports
ang.lib
Microsoft (R) COFF/PE Dumper Version 12.00.31101.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file mlang.lib

File Type: LIBRARY

     Exports

       ordinal    name

                  _ConvertINetMultiByteToUnicode
                  _ConvertINetReset
                  _ConvertINetString
                  _ConvertINetUnicodeToMultiByte
                  _DllCanUnloadNow
                  _DllGetClassObject
                  _GetGlobalFontLinkObject
                  _IsConvertINetStringAvailable
                  _LcidToRfc1766A
                  _LcidToRfc1766W
                  _Rfc1766ToLcidA
                  _Rfc1766ToLcidW

  Summary

          BD .debug$S
          14 .idata$2
          14 .idata$3
           4 .idata$4
           4 .idata$5
           A .idata$6
以上の通り、OBJファイルの関数名_ConvertINetMultiByteToUnicode@24とLIBファイルの関数名_ConvertINetMultiByteToUnicodeとは末尾@24の有無により一致しないため失敗です。
Visual C++ 2013でのConvertINetMultiByteToUnicodeにかかわる定義を以下に示します。
winnt.h
#define EXTERN_C    extern "C"
typedef _Return_type_success_(return >= 0) long HRESULT;
#define STDAPICALLTYPE          __stdcall
#define STDAPI                  EXTERN_C HRESULT STDAPICALLTYPE
mlang.h
STDAPI ConvertINetMultiByteToUnicode(_Inout_opt_ LPDWORD lpdwMode, _In_ DWORD dwEncoding, _In_opt_ LPCSTR lpSrcStr, _Inout_opt_ LPINT lpnMultiCharCount, _Out_writes_opt_(*lpnWideCharCount) LPWSTR lpDstStr, _Inout_opt_ LPINT lpnWideCharCount); 
extern "C"宣伝されているため関数名の修飾なし、__stdcallなので呼び出された側で引数で使用したスタックエリアを解放することを示します。
extern "C"を使用した場合、関数名の修飾はないはずですが、_stdcallを宣言したことにより末尾に関数名の修飾が発生しています。
末尾の@24は引数で24バイト使用しているという意味です。
_stdcallはWindowsのAPIで使用されており、何らかの手段で末尾の@24有りでDLL内の末尾@24なしのConvertINetMultiByteToUnicode関数が呼び出せるのでうまく処理されていることがわかります。
ちなみにDEFファイルでConvertINetMultiByteToUnicode@24=ConvertINetMultiByteToUnicodeのように記述すると、呼び出し名がConvertINetMultiByteToUnicode@24がConvertINetMultiByteToUnicodeに変換されるので、 リンクは正常にできますが、実行時に関数を見つけることができない旨のエラーが発生します。
これはLIBファイル側の関数名のマッチング方法が指定されており、指定方法によっては先頭や末尾の文字列を無視することができるからです。
関数名のマッチングルールは以下の3つがあります。
オブジェクトファイルで使う名前と等しい。 IMPORT_OBJECT_NAME
オブジェクトファイルで使う名前から先頭を取ったもの。IMPORT_OBJECT_NAME_NO_PREFIX
オブジェクトファイルで使う名前から先頭を取り、 さらに @ 以降の末尾も無視したもの。IMPORT_OBJECT_NAME_UNDECORATE
したがって、DLL内のAPIを呼び出すLIBファイルを作成するためにはIMPORT_OBJECT_NAME_UNDECORATEでなければなりません。
APIを正常に呼び出せるLIBファイルを作成するには、コンパイラを使ってLIBファイルを作成します。
以下のようにダミーの関数を作成します。引数は24バイトになるように適当に作成すればよいです。 mlang.cpp
extern "C" {
	void __stdcall ConvertINetMultiByteToUnicode(int,int,int,int,int,int){
	}
}
以下のようにコマンドラインでビルドすると希望のLIBファイルmlang.libが作成されます。
cl /LD mlang.cpp /link /NODEFAULTLIB /noentry /def:mlang.def
このLIBファイルを指定すると以下のコードの様に、ConvertINetMultiByteToUnicode APIを使うことができます。
//	EUC文字列をUNICODEに変換するサンプル
//	静的リンクでConvertINetMultiByteToUnicode  APIを呼び出す
//	Visual C++ 2008/2013 Unicode

#include <windows.h>
#include <stdio.h>
#include <mlang.h>
#include <tchar.h>
#include <locale.h>

#pragma comment(lib,"mlang.lib")

void _tmain(int argc,TCHAR** argv){
	// 雀の往来 9byte
	unsigned char euc[] = { 0xbf, 0xfd, 0xa4, 0xce, 0xb1, 0xfd, 0xcd, 0xe8, 0 };

	//	UNICODE文字を標準出力に正しく表示させるためにロケールを設定
	_tsetlocale(LC_ALL, _TEXT(""));

	WCHAR utf16[1024];
	DWORD mode;
	int len = sizeof(utf16) / sizeof(WCHAR);
	//	EUCをUNICODEに変換
	ConvertINetMultiByteToUnicode(&mode, 51932, (char*)euc, 0, utf16, &len);
	_putts(utf16);
}
作成されたLIBファイルのエクスポート名を確認すると以下の通りです。
OBJファイルの呼び出し名とLIBファイルのエクスポート名が一致していることがわかります。
DLLのエクスポート名が、ConvertINetMultiByteToUnicodeですので、_ConvertINetMultiByteToUnicode@24の赤の部分が無視されてうまく呼び出せることがわかります。
D:¥>dumpbin /exports mlang.lib
Microsoft (R) COFF/PE Dumper Version 12.00.31101.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file mlang.lib

File Type: LIBRARY

     Exports

       ordinal    name

                  _ConvertINetMultiByteToUnicode@24

  Summary

          BD .debug$S
          14 .idata$2
          14 .idata$3
           4 .idata$4
           4 .idata$5
           A .idata$6

プログラムソースの概要

とライブラリファイルをリンクして作成されたconv2str.exe ConvertINetMultiByteToUnicode APIをサポートするライブラリファイルmlang.libを作成するためのmlang.defとmlang.cpp、 呼び出しテストを行うconvstr2.cppで構成されています。

mlang.def

ライブラリファイルのエクスポート名を指定しています。

mlang.cpp

ライブラリファイルを作成するためのダミーのソースファイルです。
戻り値および引数の型は適当ですが引数の合計バイト数はAPIと一致させる必要があります。
convstr2では、ConvertINetMultiByteToUnicode関数しか使用していませんがついでですので、ConvertINetUnicodeToMultiByteもライブラリ化します。

convstr2.cpp

このソースはUNICODE専用です。
_tsetlocale関数によりUNICODEでの標準エラー出力を正常に行えるように設定します。
EUC文字列には、他の文字コードで解釈すると必ず解読不可能な文字列になるため使われる雀の往来を使用しています。
ConvertINetMultiByteToUnicode APIによりEUC文字列をUNICODEに変換します。
_putts関数によりUNICODE文字列を標準出力に出力します。

プログラムソース

mlang.def

LIBRARY "mlang.dll"
EXPORTS
 ConvertINetMultiByteToUnicode
 ConvertINetUnicodeToMultiByte

mlang.cpp

extern "C" {
	void __stdcall ConvertINetMultiByteToUnicode(int,int,int,int,int,int){
	}
	void __stdcall ConvertINetUnicodeToMultiByte(int,int,int,int,int,int){
	}
}

convstr2.cpp

//	EUC文字列をUNICODEに変換するサンプル
//	静的リンクでConvertINetMultiByteToUnicode  APIを呼び出す
//	Visual C++ 2008/2013 Unicode

#include <windows.h>
#include <stdio.h>
#include <mlang.h>
#include <tchar.h>
#include <locale.h>

#ifdef _WIN64
	#pragma comment(lib,"mlang64.lib")
#else
	#pragma comment(lib,"mlang.lib")
#endif

void _tmain(int argc,TCHAR** argv){
	// 雀の往来 9byte
	unsigned char euc[] = { 0xbf, 0xfd, 0xa4, 0xce, 0xb1, 0xfd, 0xcd, 0xe8, 0 };

	//	UNICODE文字を標準出力に正しく表示させるためにロケールを設定
	_tsetlocale(LC_ALL, _TEXT(""));

	WCHAR utf16[1024];
	DWORD mode;
	int len = sizeof(utf16) / sizeof(WCHAR);
	//	EUCをUNICODEに変換
	ConvertINetMultiByteToUnicode(&mode, 51932, (char*)euc, 0, utf16, &len);
	utf16[len] = 0;
	_putts(utf16);
}

ソースファイルのダウンロード

ダウンロード mlang.zip(103kByte)
ZIPファイルにはVisual C++ 2013用の以下のファイルが含まれています。
vc2013
 ├─convstr2
 │      convstr2.cpp	C++ソースファイル
 │      convstr2.exe	convstr2.cppとmlang.libから成された32bit実行ファイル
 │      convstr2_64.exe	convstr2.cppとmlang64.libから作成された64bit実行ファイル
 │      
 └─mlang
         mlang.cpp
         mlang.def
         mlang.lib	malng.cppとmlang.defから作成された32bitライブラリファイル
         mlang64.lib	mlang.defから作成された64bitライブラリファイル