管理人個人メモ/DLL/DLL2

Last-modified: 2011-09-21 (水) 16:54:36

DLLの種類について

http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1236065252
http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1435959544
によると、DLLには、次のような種類があるらしい。

  1. Win32 DLL
  2. .NET仕様
  3. COM形式のDLL

Win32 DLL

おそらく、アンマネージなDLLという言葉と同義だと思う?
(むしろ、アンマネージなDLLという言葉の方がよくみかける)
また、ネイティブという言葉もよく見かける。この場合は必ずマネージドと対比する形で検索。

VC6.0以前に多い。
おそらく、HSPがDLLと呼んでいるものも、こちらに含まれると思われる。
基本的に関数形式で、クラスはできなくはない(後述)。
C言語が基本。
 
クラス単位でDLLを作ると、DLLファイル(拡張子.dll)と
静的ライブラリ(拡張子.lib)の2つファイルが作成されるらしい。
(.hとDLLでもいいような気がする?が詳細不明)
 
Win32形式のPGと、C#やVB.NET等の.NET形式のPGでは、全く違う規格で、
Win32形式での静的ライブラリは、C#で利用するのは無理とのこと。
 

そこで、以下の方法でラップしてしまうことで、
C#からC++のライブラリを使用することができるようになるらしい。
http://www.atmarkit.co.jp/fdotnet/special/vcppinvista01/vcppinvista01_03.html
 
他にも、ラップしなくても、
C#から、直接アンマネージなコードを呼び出すコードが数多く紹介されている。

.NET仕様

プロジェクトのプロパティで出力をクラスオブジェクトにしておくと吐けるDLLで、
マネージドなDLLなどと呼ばれているものと同義だと思う?
 
VBや、C#だと、ソリューションエクスプローラーの[参照設定]から、
簡単にクラスをインポートできる。
その際に、.hがいらない模様?
 
基本的に、C#やVBでのDLLと思われる。
VC++.NETのCLRプロジェクトで作成したDLLも該当するが、
C++/CLIと言う、文法的にはC++とC#の中間の位置にある言語を使用することになるらしい。
純粋なC++は使えないとのこと。
  
Win32の項目で述べたのは、C++で作成したDLLをC#から呼び出すものだったが、
逆に、C#で作成したDLLをC++で呼び出す方法はこちら。
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200509/05090014.txt
(念のため、コピー

↑と思ったけど、どうやら、普通にCLRプロジェクトのC++から叩いているソースのような気がする。
 Win32からC#のDLLをたたけないものか・・・ ⇒ COMを経由すれば叩ける(後述)

COM形式のDLL

作るのは大変らしいが、
使う側から見れば、.NETの[参照設定]で、同様に使えるらしい。
VC++.NETのATLプロジェクトで作成可能らしい。
 
C#で書いたDLLをCOM化することができる。(後述)

Win32 DLLでクラスや構造体をやり取りする場合

インポート側にも、クラスの定義が必要である。
DLLの明示的リンクでは、

typedef int ( __cdecl *OKiHo)(double b , double c);

のように、関数の型を宣言していたが、
このintがクラスだったり、構造体だったりすると、
それが何者であるかを示すための、.hファイルが必要である。
(DirectXとかでも、DLLの利用に.hが必要である)
 
したがって、HSPでも、同様のものをdimなどで定義してやれば
可能だと思われるが、ハードルは高いかもしれない。
 
具体的なインポート、エクスポートの方法は、
Win32のDLLをスケルトンつきで(空にチェックを入れないで)新規作成してみればわかる。

参照設定の仕方(C#, VB, C++ ) [#yce43d15]

http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1020326470
外部のクラスライブラリの指定方法は、
VB,C#,C++とも上記のリンクに乗っている。
C#なら簡単にできたが、C++だとなぜかできなかった。
(指定のリンクはあるけど、DLLの指定ができない)

解決:
プロジェクトの種類は「Windowsファームアプリケーション」等の新仕様でのプロジェクトなら何でもOKです(MFCやCOM等の旧仕様のプロジェクトは、もちろん無理です)

無理な方には、Win32アプリケーションも含まれる。

なんとか、ラッパーとかかけて、.NETのDLLをWin32用にできないか。

http://oshiete.goo.ne.jp/qa/5148995.html
で得た情報で
(※ただし、上記サイトで議論されているのは逆の内容で、
 アンマネージのC++をC++/CLIで使う方法に関する議論である)、

Win32のプロジェクトでも、
「共通言語ランタイム サポート」項目で「共通言語ランタイム サポート(/clr)」を選択
とすると、参照設定ができるようになるが、
どうも、うまく機能しない様子。

<↓以下の項目を追記>

マネージドなDLLとアンマネージドなDLLの相互運用

いくつかアイデアがある。

CLRプロジェクトは、C++/CLIというマネージドなCなので、これを使う。

 http://oshiete.goo.ne.jp/qa/5148995.html
 ⇒ただ、マネージドなCは、普通のCと結構違う様子。
  Cと直接やりとりできるから、型の変換がいらないのは強いかもしれない。
  参照設定はプロパティからできるけど、他のDLLの呼び出し方もよくわからんし、
  <s>ちょっと試したけど、断念。</s>

 
(11.9.21追記)
CLR ⇒ ネイティブCは、
COM化しなくてよいのがでかい!
そして、配列も普通に渡せるし、
ネイティブと、マネージドコードを同じファイルに書くことも可能だ。
 
DLLの呼び出し規約もCのときとまったく同じ。
COMは、関数の宣言と引数、戻り値の宣言、型の変換など異様に面倒なので、
こちらでやった方がいいと思い始めた。


// CLRDLL.h

#pragma

using namespace System;

namespace CLRDLL {

	public ref class Class1
	{
	public:
		// TODO: このクラスの、ユーザーのメソッドをここに追加してください。
		int uga(int dd[])
		{
			Console::WriteLine("aaa" + dd[0] + ":::" + dd[1]);
			return 1;
		}
	};
}


#define

EXPORTS int _cdecl test(){
	int aa[5];
	aa[0] = 1;
	aa[1] = 2;
	CLRDLL::Class1 c1;
	c1.uga(aa);
	return 5;
}

COM化する

 http://satoshi.web5.jp/memo/connect_dll.htm##2
 ⇒一番、有用な手段に思える。違う言語でやってもOKなのが強い。
  C#のプロジェクトのプロパティから、COM化OK的なチェックを入れて、
  後で、regasm /codebase Hogehoge.DLL としてレジストリに登録する。
  解除するときは、regasm /u Hogehoge.DLL
  #参考サイトには、自動でレジストリに登録されるとあるが、されなかった。
   
  http://d.hatena.ne.jp/nitoyon/20080731/c_sharp_com
  RegAsmは、c:\Windows\Microsoft.NET\Framework\v4.0.30319 にある。
  最後のv4. …のところは、バージョン番号だから、C#側で吐き出したバージョンに
  合わせておいた方がいいだろうなとは思う。(ずれてても動いたけど)

  また、呼び出し側のコンパイルは、clで、とあるが、
  ふつうにIDEからコンパイルで大丈夫だった。
  ちなみに、clはコマンドラインからでは呼び出せなくて、
  Visual Studio用のコマンドラインでなければだめ(プログラム一覧の中にある)

REGASMトラブルシューティング

 なお、REGASMが正常に実行されるには、UACに注意しなければいけない。
 もし、制限がかかっている場合は、解除しないと駄目。
 
  「RegAsm : warning RA0000 : 型は何も登録されませんでした。」

  COM可能にするという対処法はたいていネット上に載っているが、
  実は、C#側のClassにpublicをつけ忘れても出るエラーである。

C#からアンマネージドなコードを呼び出す場合

 この場合は、COM化しなくてもよい。
 http://satoshi.web5.jp/memo/connect_dll.htm##2

 特に難しい接続などはありません
 .NET側で [DllImport("xxxxx.dll")]と宣言してやるだけで他のメソッドと同様に扱うことができます
 問題はパラメータの受け渡しです!

 とのこと。
 パラメータの受け渡しは、マーシャリングなどと呼ばれているようす。
 マーシャリングとは、もともと、違う環境に適応させるための変換という意味らしい。
 
 そもそも、アンマネージドなコードを呼び出すための仕組みがあるようで、P/Invokeと呼ばれている。

マーシャリングに関する資料

マネージドからアンマネージドを呼び出す場合

 http://satoshi.web5.jp/memo/connect_dll.htm##2
 http://msdn.microsoft.com/ja-jp/library/ms384314(v=vs.71).aspx
 http://msdn.microsoft.com/ja-jp/library/sd10k43k(v=vs.80).aspx
 http://gurizuri0505.halfmoon.jp/20100317/13794
 http://xptn.dtiblog.com/blog-entry-110.html
 http://d.hatena.ne.jp/Schima/20090620/1245425357
 http://msdn.microsoft.com/ja-jp/library/z6cfh6e6(v=vs.80).aspx
http://maaash.jp/c/c%EF%BC%83%E3%81%A8%E3%82%A2%E3%83%B3%E3%83%9E%E3%83%8D%E3%83%BC%E3%82%B8%E3%83%89c%E3%81%AEdll%E9%96%93%E3%81%A7%E6%96%87%E5%AD%97%E5%88%97%E3%81%AE%E9%85%8D%E5%88%97%E3%82%92%E3%82%84%E3%82%8A/
 http://webcache.googleusercontent.com/search?q=cache:LTYZjrfS0bUJ:rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi%3Fprint%2B200908/09080038.txt+byte+%22unsigned+char%22+%E5%A4%89%E6%8F%9B&cd=20&hl=ja&ct=clnk&gl=jp

 

}}