読者です 読者をやめる 読者になる 読者になる

「Androidは電気羊の夢を見るか」を読みたい管理者のブログ

仕事などでの色々な発見を記事にしてます。不定期更新。

dllファイルの作り方、使い方

はじめに

の(はてな記法による)焼き直しです。中身大して変わってません<(`^´)>

目的

C++で作成されたdllをC#C++のコードから使おうとするとやや複雑な手順を要する。
dllは関数をエクスポートせねばならず、dll側は関数をインポートせねばならないからだ。
初心者がまず最初に躓くポイントとしてリンカーエラーが挙げられるだろう。
以下に示す手順で順番に作成していけば順調にいくはずである。
では検討を祈る。

(ここではVisualStudio2008を例に説明を行う。しかし基本的な考え方はVSのバージョンが違っても変わらない。事実ぼくはつい最近までVS6.0でのdllの作り方しか知らなかった。)

概要

C++C#では以下の組み合わせが考えられる。

インポート\エクスポート C++ C#
C++ C++からC++dllをインポート C#からC++をインポート
C# C++からC#をインポート C#からC#をインポート

ここではC#からC#のdllの参照は扱わない。なぜならあまりに簡単だからだ。また、C++からC#で作成されたdllの参照も解説しない。なぜなら根本的に不可能だからだ。

まず基本的な考え方を述べる。
dllファイルとdllファイル内に関数を突っ込んだだけではその関数を呼び出すことはできない。そのために関数のエクスポートという概念が必要になる。
エクスポート・・日本語でいえば輸出だ。dllは関数を輸出している。
また、dll内部の関数を呼び出したい時、インポートと呼ばれる処理が必要になる。日本語でいえば輸入だ。
どうだ。一つの教訓を得るだろう。インポートされるためにはエクスポートされなければならない。すなわち、輸入するためにはどこかの国が輸出せねばならない。

C++dllプロジェクトの作成

dllプロジェクトの作成の仕方

①空のプロジェクトを作成します。

②プロジェクトのプロパティ→構成プロパティ→全般の中にある構成の種類を「ダイナミックリンクライブラリ(.dll)と指定します。

③OKボタンを押します。

C++dllからの関数のエクスポートの仕方

http://msdn.microsoft.com/ja-jp/library/d91k01sh.aspx
このページを参考にしてくれ。
拡張子が.defになってるファイルを作成するだけだ。簡単だろう?

defファイル(モジュール定義ファイル)の構成は以下の通りだ

LIBRARY (ここにdllの名前)
EXPORTS
(ここに関数の名前) @(連番)

(連番)は1から2,3,4,5と順番に増えて行く。番号が被るとコンパイルエラーになるから注意が必要だ。

プロジェクトのプロパティ>リンカー>入力>モジュール定義ファイルに作成した.defファイルが指定されていることを確認しよう。
もし指定されてなかったら作成した.defファイルを指定しよう。
※こうしないと.libファイルが作成されないんだ。

これを行うだけでC#からでも、C++からでもdll内部の関数を呼び出すことが可能となる。

C++exeからのdll関数のインポート

上記のdefファイルを作成してコンパイルを通すと拡張子がlibになったファイルが作成される。
C++でdllを使いたいと言った場合はコンパイラにこのlibファイルを使うよと指示を出す必要がある。

http://msdn.microsoft.com/ja-jp/library/ba1z7822.aspx

を参考にlibファイルを追加の依存ファイルに追加する。

※ビルドする時点ではプロジェクトファイルがあるディレクトリがカレントディレクトリとなっているため、そこからの相対パス、または絶対パスを指定する必要がある。

dllファイルのインポート(C#の場合)

色々な流派があるらしい。が、僕はCallDLLクラス内で呼び出すのが好きだ。

using System.Runtime.InteropServices;

を追加して

[DllImport("dllproject2.dll")]
extern public static (dll内の関数名)(関数の引数)

と定義するだけで、dll内の関数をC#から利用する事が出来る。

using System.Runtime.InteropServices;
static class CallDLL
{
  [DllImport("dllproject2.dll")]
  extern public static Int32 dllfunc();
}

呼び出す時に

  CallDLL.dllfunc()

と書いてあげればよい。