豚吐露@wiki
VC++でDLLを作る
最終更新:
Bot(ページ名リンク)
-
view
VC++2005でDLLを作る
Windows XP SP3
Visual Studio 2005
Visual Studio 2005
■DLLの作り方
VS起動。
[ファイル]-[新規作成]-[プロジェクト]
ダイアログの左のプロジェクトの種類から[Visual C++]-[Win32]選択。右のテンプレートから[Visual Studioにインストールされたテンプレート]-[Win32 プロジェクト]を選択。
適当なプロジェクト名を入力、適当な場所を設定してOK押下。とりあえずここでは『PjHoge』って名前で進める。
Win32アプリケーションウィザードへようこそが立ち上がるので次へ押下。
アプリケーションの種類で『DLL』を選択。
共通ヘッダーファイルを追加の『ATL』『MFC』はチェックしない。
※なんかチェックしたら『fatal error C1189: #error : Building MFC application with /MD[d] (CRT dll version)
requires MFC shared dll version. Please #define _AFXDLL or do not use /MD[d]』とかエラー出てRelease buildができんくなった。ようわからんのんで、ちゃんと理解せんと使えなさそう。
で、完了押下。
VS起動。
[ファイル]-[新規作成]-[プロジェクト]
ダイアログの左のプロジェクトの種類から[Visual C++]-[Win32]選択。右のテンプレートから[Visual Studioにインストールされたテンプレート]-[Win32 プロジェクト]を選択。
適当なプロジェクト名を入力、適当な場所を設定してOK押下。とりあえずここでは『PjHoge』って名前で進める。
Win32アプリケーションウィザードへようこそが立ち上がるので次へ押下。
アプリケーションの種類で『DLL』を選択。
共通ヘッダーファイルを追加の『ATL』『MFC』はチェックしない。
※なんかチェックしたら『fatal error C1189: #error : Building MFC application with /MD[d] (CRT dll version)
requires MFC shared dll version. Please #define _AFXDLL or do not use /MD[d]』とかエラー出てRelease buildができんくなった。ようわからんのんで、ちゃんと理解せんと使えなさそう。
で、完了押下。
プロジェクト以下にPjHoge.cppってファイルがあるので開く。
欲しい関数を作成。
デフォで『DllMain()』があるので、関数を書くのはその並びに記述。とりあえず、ファイル末尾で良い。
で、お約束。関数宣言の前に『__declspec(dllexport)』を書く。
欲しい関数を作成。
デフォで『DllMain()』があるので、関数を書くのはその並びに記述。とりあえず、ファイル末尾で良い。
で、お約束。関数宣言の前に『__declspec(dllexport)』を書く。
e.g.)
int funcHoge(const char *hogeParam) って関数だったら __declspec(dllexport) int funcHoge(const char *hogeParam) ってする。
dll内部からcallされること無いんだったらプロトタイプ宣言は不要。
で、C++ってコンパイルすると勝手に関数名変わっちゃうので、変わらないようにする。
cppファイルと同じdirに適当なdefファイルを作成して、以下のように記述。とりあえず、Pj名.defにする。
cppファイルと同じdirに適当なdefファイルを作成して、以下のように記述。とりあえず、Pj名.defにする。
e.g.)PjHoge.def
EXPORTS funcHoge PRIVATE
ここに書くPRIVATEの意味が分からんが、とりあえず、上記のように書けば良いらしい。
で、ソリューションエクスプローラでプロジェクト名を右clickしてプロパティを選択。
左のtreeから[構成プロパティ]-[リンカ]-[入力]を選択。
右に出てきた中に『モジュール定義ファイル』って項目があるので、ここに『PjHoge.def』を書く。CPPファイルと違う場所にdefファイル置いたんだったら、相対pathで書いてやれば問題無いハズ。
この時、左上の構成ってドロップダウンリストで選ばれとるのにしか設定されんのに注意。例えば構成でDebugが選択されてる状態でdefファイル設定しても、Releaseに変えるとモジュール定義ファイルが空欄になる。まぁ、用意されとる構成全てに書かなきゃダメよって事。
左のtreeから[構成プロパティ]-[リンカ]-[入力]を選択。
右に出てきた中に『モジュール定義ファイル』って項目があるので、ここに『PjHoge.def』を書く。CPPファイルと違う場所にdefファイル置いたんだったら、相対pathで書いてやれば問題無いハズ。
この時、左上の構成ってドロップダウンリストで選ばれとるのにしか設定されんのに注意。例えば構成でDebugが選択されてる状態でdefファイル設定しても、Releaseに変えるとモジュール定義ファイルが空欄になる。まぁ、用意されとる構成全てに書かなきゃダメよって事。
ここまでやって、buildする。
上記手順を踏まないと、dllが出来ても呼び出せない。DllNotFoundExceptionとかEntryPointNotFoundExceptionが発生する。
上記手順を踏まないと、dllが出来ても呼び出せない。DllNotFoundExceptionとかEntryPointNotFoundExceptionが発生する。
メモ
EntryPointNotFoundException:DLL内に指定の関数が無い時に発生。呼び出し元で関数名間違えとったり、DLLのプロジェクトでdefファイル設定してなかったりした場合に発生するっぽ。
DllNotFoundException:対象のDLLが見つからない場合に発生する。ただ、たちが悪いのは、DLL内で使用しているDLLが無くても発生して、その時の警告に最上位のDLL名しか載っとらんかったりする。プロジェクト作成時にATLやMFCのcheck入れてると起きたりする。解決方法はよう分からん。つか、ちゃんと調べてない。
EntryPointNotFoundException:DLL内に指定の関数が無い時に発生。呼び出し元で関数名間違えとったり、DLLのプロジェクトでdefファイル設定してなかったりした場合に発生するっぽ。
DllNotFoundException:対象のDLLが見つからない場合に発生する。ただ、たちが悪いのは、DLL内で使用しているDLLが無くても発生して、その時の警告に最上位のDLL名しか載っとらんかったりする。プロジェクト作成時にATLやMFCのcheck入れてると起きたりする。解決方法はよう分からん。つか、ちゃんと調べてない。
まず、Pjを作成。
VSのメニューから[ファイル]-[新規作成]-[プロジェクト]を選択。
ダイアログの左のプロジェクトの種類から[他の言語]-[Visual C#]選択。右のテンプレートから[Visual Studioにインストールされたテンプレート]-[コンソール アプリケーション]を選択。適当なプロジェクト名と場所を入力して『OK』押下。
すると、Main関数だけのProgram.csってファイルだけのプロジェクトができあがる。
VSのメニューから[ファイル]-[新規作成]-[プロジェクト]を選択。
ダイアログの左のプロジェクトの種類から[他の言語]-[Visual C#]選択。右のテンプレートから[Visual Studioにインストールされたテンプレート]-[コンソール アプリケーション]を選択。適当なプロジェクト名と場所を入力して『OK』押下。
すると、Main関数だけのProgram.csってファイルだけのプロジェクトができあがる。
このcsファイルちょちょっといじってやる。
- usingの追加。
DLLを呼び出す機能を使うために、以下の1行をusingに追加。
using System.Runtime.InteropServices;
- DLL中の関数登録
class直下に以下を追加。
[DllImport("funcHoge ")] static extern int funcHoge(string hogeParam);
ここで注意せんといけんのは、C++側とC#側では必ずしも型が一致しないこと。
今回の場合だとC++では『const char *』だったのが、C#では『string』に変わっとる。
OUTの引数とかだとref付けてあげたり、バイナリデータ(unsighed charの配列)だったら型をbyte[]にして、BinaryReaderクラス渡してあげたりとかせにゃいけん。
call失敗したらここら辺が原因かな?
今回の場合だとC++では『const char *』だったのが、C#では『string』に変わっとる。
OUTの引数とかだとref付けてあげたり、バイナリデータ(unsighed charの配列)だったら型をbyte[]にして、BinaryReaderクラス渡してあげたりとかせにゃいけん。
call失敗したらここら辺が原因かな?
で、使用するための準備が終わったら、callする処理を追加。とりあえず、Main関数に書いてみるテスト。
e.g.)
e.g.)
: using System.Runtime.InteropServices; : class Program { [DllImport("funcHoge ")] static extern int funcHoge(string hogeParam); static void Main(string[] args) { int ret = funcHoge("call Hoge"); } }
これで実行させるとDLLに書いたfuncHogeの処理が行われるハズ。
更新日: 2011年09月14日 (水) 16時22分09秒