どうにも私が文章を書くと無駄に長文になるきらいがあるので、DLLの作り方を知っている方向けに要点だけ先に書きます。
__stdcall とすること。EXPORTS セクションには名前空間抜きの関数名(とその序数)を書く。nspaceX::func 関数をエクスポートするなら func @1 といった感じで書く。int& 等)は使わず、ポインタ型で代用すること。*3要点は以上。
以降はもうちょっとだけ詳しく解説した長文です。
Visual C++ でDLLを作る際、他の言語からでも利用可能な汎用DLLとするには、次のことを守る必要があります。
__stdcall とする。*4__declspec(dllexport) を使うのではなく、DEFファイルでエクスポートする関数を定義する。ちなみに、DLLの作り方を解説しているサイトで「C++で作る場合は extern "C" が必要」という記述をよく目にしますが、これは __declspec(dllexport) を使う場合の話です。
DEFファイルを使って関数をエクスポートする場合、言語がC++であっても extern "C" は不要です。(付けてもいいですが)
ただし、それでも関数オーバロードは使えないと思った方がいいでしょう。(関数オーバロードをDEFファイルで解決する方法がわかりません…)
さて、関数をエクスポートするのはいいのですが、DLLの作り方を解説しているサイトの多くではグローバル名前空間の関数をエクスポートする例が載っています。
C++的には、不特定多数に公開する関数やクラスをグローバル名前空間に置くのは避けたいものです。
自分で定義した名前空間(namespace)内に置いた関数をエクスポートすることはできないのでしょうか。
結論から言えばできます。
全く制約が無いわけではないですが、特に難しい記述をすることもなく普通にエクスポートできます。
以降の記述は Visual Studio 2012 Update3 での操作を前提としています。
古いバージョンの Visual Studio ではできないかもしれません。
まずはサンプルのDLLを作成してみましょう。
LIBRARY sampleDll
EXPORTS
addAB @1
subAB @2
こうしてできあがったサンプルDLLの使い方ですが、静的リンク(sampleDll.lib を使ってリンク)するか動的リンク(実行時にDLLをロード)するかによって変わります。
LoadLibrary 関数と GetProcAddress 関数を用いる場合は次のように記述すればOKです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | - ! - ! - - ! | - - ! | | - - ! ! | - ! ! | | ! | |
制限事項などについてはこの記事の冒頭を参照してください。
なお、今回作成した sampleDll.dll のエクスポートテーブルを Visual Studio のツールである dumpbin で調べると、次のような感じに出力されます。
>dumpbin /exports sampleDll.dll
Microsoft (R) COFF/PE Dumper Version 11.00.60610.1
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file sampleDll.dll
File Type: DLL
Section contains the following exports for sampleDll.dll
00000000 characteristics
521CAB3B time date stamp Tue Aug 27 22:35:55 2013
0.00 version
1 ordinal base
2 number of functions
2 number of names
ordinal hint RVA name
1 0 00011023 addAB = @ILT+30(?addAB@sampleDll@@YGHHH@Z)
2 1 0001101E subAB = @ILT+25(?subAB@sampleDll@@YGHHH@Z)
Summary
1000 .data
1000 .idata
2000 .rdata
1000 .reloc
1000 .rsrc
4000 .text
10000 .textbss
真ん中あたりを見ると、 addAB や subAB がちゃんと名前空間付きでエクスポートされていることがわかると思います。