[[How2Computing]] #author("2022-01-13T19:14:49+09:00","","") -関連トピックス --[[Mac OS X の Xcodeでライブラリを作る:http://is.ocha.ac.jp/~gradthesis/index.php?How2dylib]] //--[[Windwos Visual Studio 2010 のC++で動的ライブラリ dll を作る:http://is.ocha.ac.jp/~gradthesis/index.php?How2dll]] --[[Windwos Visual Studio 2010 で静的ライブラリ lib を作る:http://is.ocha.ac.jp/~gradthesis/index.php?How2lib]] --[[ccで作ったライブラリ(dylib)をJava (JNA) から使う(Mac OS X 編)::http://is.ocha.ac.jp/~gradthesis/index.php?How2lib]] *Windwos Visual Studio 2010 のC++で動的ライブラリ dll を作る [#ha82739a] http://bluefish.orz.hm/sdoc/dll_memo.html を参考にしました。 C++で作ったdllは、C#やVisual Basicなどから利用できます。 **簡単なdllをC言語で作る [#b401529e] Visual Studio 2010から「新しいプロジェクト」「Win32コンソールアプリケーション」を選ぶ。名前は、mydllとしておく。 //http://gyazo.com/53ae6ce82b868f6462e56bdca34d368e.png http://is.ocha.ac.jp/~gradthesis/gyazo/53ae6ce82b868f6462e56bdca34d368e.png 次に開くアプリケーションウィザードで、アプリケーションの種類をDLLにして, 追加のオプションとして、シンボルのエクスポートを選ぶ。 http://gyazo.com/ac8a4bbcbb4418dfae833ad54c66077e.png mydll.hを見ると以下のようになっている。 // 以下の ifdef ブロックは DLL からのエクスポートを容易にするマクロを作成するための // 一般的な方法です。この DLL 内のすべてのファイルは、コマンド ラインで定義された MYDLL_EXPORTS // シンボルを使用してコンパイルされます。このシンボルは、この DLL を使用するプロジェクトでは定義できません。 // ソースファイルがこのファイルを含んでいる他のプロジェクトは、 // MYDLL_API 関数を DLL からインポートされたと見なすのに対し、この DLL は、このマクロで定義された // シンボルをエクスポートされたと見なします。 #ifdef MYDLL_EXPORTS #define MYDLL_API __declspec(dllexport) #else #define MYDLL_API __declspec(dllimport) #endif // このクラスは mydll.dll からエクスポートされました。 class MYDLL_API Cmydll { public: Cmydll(void); // TODO: メソッドをここに追加してください。 }; extern MYDLL_API int nmydll; MYDLL_API int fnmydll(void); ここではC形式でエクスポートするように変更する。 また、変数、関数、クラスをエクスポートする雛形となっているが、 今回は、関数しか使わないので、以下のように書き換える。 // 以下の ifdef ブロックは DLL からのエクスポートを容易にするマクロを作成するための // 一般的な方法です。この DLL 内のすべてのファイルは、コマンド ラインで定義された MYDLL_EXPORTS // シンボルを使用してコンパイルされます。このシンボルは、この DLL を使用するプロジェクトでは定義できません。 // ソースファイルがこのファイルを含んでいる他のプロジェクトは、 // MYDLL_API 関数を DLL からインポートされたと見なすのに対し、この DLL は、このマクロで定義された // シンボルをエクスポートされたと見なします。 #ifdef MYDLL_EXPORTS #define MYDLL_API extern "C" __declspec(dllexport) #else #define MYDLL_API extern "C" __declspec(dllimport) #endif MYDLL_API int myAdd(int a, int b); ちなみにここで作ってみる関数は、int myAdd(int a, int b);という関数である。 mydll.cppを見てみると、mydll.hに合わせて以下のようになっている。 // mydll.cpp : DLL アプリケーション用にエクスポートされる関数を定義します。 // #include "stdafx.h" #include "mydll.h" // これは、エクスポートされた変数の例です。 MYDLL_API int nmydll=0; // これは、エクスポートされた関数の例です。 MYDLL_API int fnmydll(void) { return 42; } // これは、エクスポートされたクラスのコンストラクターです。 // クラス定義に関しては mydll.h を参照してください。 Cmydll::Cmydll() { return; } mydll.hを書き換えてしまったので、それに合わせて、以下のようにしてみよう。 作った関数は足し算する関数である。 // mydll.cpp : DLL アプリケーション用にエクスポートされる関数を定義します。 // #include "stdafx.h" #include "mydll.h" // これは、エクスポートされた関数の例です。 MYDLL_API int myAdd(int a, int b) { return a+b; } これを「ビルド」「ソリューションのビルド」すると、DebugまたはReleaseフォルダに、 -mydll.dll -mydll.lib ができあがる。またmydllフォルダに、 -mydll.h が出来上がる。この3個のファイルを、使えば、他のプログラムからこの関数を使えるようになる。 **上で作ったdllを他のC言語で使ってみる [#z4c14b32] 必要なものは、 -mydll.dll -mydll.lib -mydll.h の3点である。 //http://gyazo.com/77ac49ce1f55bacbe471aba91b6652c4.png http://is.ocha.ac.jp/~gradthesis/gyazo/77ac49ce1f55bacbe471aba91b6652c4.png Visual Studio 2010でtestdllという名前のWin32コンソールアプリケーションプロジェクトを新規につくる。 プロジェクトにファイルを追加する方法はいろいろあるらしいけど、ややこしいので、 mydll.libとmydll.hをtestdll.cppのあるフォルダにコピーしてしまった。 mydll.dllは、PATHの通った場所か、実行ファイルの場所に置く必要がある。 ややこしいので、後者をとって、Debug(かRelease)の場所に置くことにした。 testdll.cppに以下のプログラムを作ることで、myAdd()関数を呼び出すことができる。(結果は5) #include "stdafx.h" #include "mydll.h" #pragma comment(lib,"mydll.lib") int _tmain(int argc, _TCHAR* argv[]) { printf("value is %d\n", myAdd(2,3)); return 0; } *上で作ったdllをC#から使ってみる [#v0600952] C# Win32コンソールアプリケーションのプロジェクトを作る。なお、 //http://gyazo.com/c64f03f29cb8d5c20afdf1fc29e839ce.png http://is.ocha.ac.jp/~gradthesis/gyazo/c64f03f29cb8d5c20afdf1fc29e839ce.png mydll.dllファイルは、実行ファイルの場所(プロジェクト名の中のbinの中のDebugかReleaseの中)に置いておく。 以下のように3行追加することで、上記のmyAdd()関数を使える。 P/Invokeという手法らしい。 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; //これを追加 namespace testlibcs { class Program { [DllImport("mydll.dll")] //これを追加 static extern int myAdd(int a, int b); //これを追加 static void Main(string[] args) { Console.WriteLine(myAdd(5, 8)); } } }