- - PR -
【C#】IMalloc.FreeとMarshal.FreeHGlobalの違い
投稿者 | 投稿内容 | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2005-12-22 19:24
清華ですよろしくお願いします。
さて早速ですがIMalloc.FreeとMarshla.FreeHGlobalには違いがあるのでしょうか? Microsoft Win32とMicrosoft .NET Framework APIとの対応のメモリ関連項目には
と書かれています、MSDNのGlobal Freeに関する記述では
IMallocに関する記述では
とかかれています、 GlobalAllocとIMalloc::Allocの違いも良く分かりません。 GlobalAlloc
IMalloc:Alloc
結局GlobalAllocでもIMalloc:Allocでもメモリブロックを割り当てるしGlobalFreeでもIMalloc::Freeでもメモリブロックを解放すると解釈していいのでしょうか? IMallocを使用するためのインターフェイスの記述などでコードが重くなりますし、Marshalのほうが簡単に使えるので区別する必要が無いならばMarshalで書くつもりです。 よろしくお願いします。 _________________ 9uiet Design - http://quietdesign.rental.allinoneserver.net/ デザインにこだわったソフトの配布とプログラミングTipsの公開(予定)をしています。 9uiet Blog - http://seiga.blog44.fc2.com/ 笑ったことやプログラミングのことなど書 | ||||||||||||||||||||||||
|
投稿日時: 2005-12-22 20:34
こんばんは。
えっと、比べる対象がちょっと違うように感じます。 IMallocインターフェイスは、あくまで「インターフェイス」ですので 自分でIMallocを実装してもいいわけであって、どのメモリ領域に領域を確保するかは実装依存なはずです。 ちなみに、 CoTaskMemAllocや CoGetMallocで得られるIMallocインターフェイスの実装や Marshal.AllocCoTaskMemは 「COM タスクメモリ」上にアロケートするようですが、 一方 GlobalAllocや Marshal.AllocHGlobalは 「グローバルヒープ」上にアロケートします。 私には、「COM タスクメモリ」と「グローバルヒープ」が、どのように違うのか知りませんが、 区別して使ったほうが良いと思います。 [ メッセージ編集済み 編集者: Tdnr_Sym 編集日時 2005-12-22 20:41 ] | ||||||||||||||||||||||||
|
投稿日時: 2005-12-22 20:47
言葉足らずでした、SHGetMallocを使ってMallocオブジェクトを作成しています、自分で実装はしませんよ(苦笑。
これですっきりしました、IMalloc::Allocの説明を見ても確保するとしか書いていなかったので(苦笑。 違う場所から持ってきているのならば区別する意義がありますね、まぁどちらにせよ Marshal.FreeCoTaskMem() * FreeCoTaskMem exposes the CoTaskMemFree COM API function * 領域の確保もMarshal.AllocCoTaskMemを使うようにしてやればこれで問題なさそうですね、in the same way that IMalloc::Alloc does.って言ってますし。 有難うございました、すっきりしました。 | ||||||||||||||||||||||||
|
投稿日時: 2005-12-22 21:20
こんばんは。
私もIMallocインターフェイスを実装したことないですね(~_~;) IStreamインターフェイスなら実装したことはありますが。(Win32リソースからデータを読み出すよう実装しました) そういえば、SHGetMallocというAPIもありましたね。 もうサポートされないようですが。
とありますので、代わりにMarshal.AllocCoTaskMemとMarshal.FreeCoTaskMemを使っても良いのでしょう。 とにかく、ちゃんと対応した関数(メソッド)を使ってAlloc/Freeすることは、最低限守ったほうがよいでしょうね。 | ||||||||||||||||||||||||
|
投稿日時: 2005-12-23 16:02
シェルオブジェクトも含めて,COMオブジェクトを相手にする場合は,
インターフェイスの参照カウントの扱いや 参照でやり取りする引数をどっちが開放するのか 等の細かい決まりがあるので, .NET Framework のマーシャリング機能にゆだねた方が無難です。 SHGetMalloc ですでに IMallocインターフェイスが返ってきているので, Marshal.GetTypedObjectForIUnknown(ptrRet, typeof(IMalloc)) の typeof(IMalloc) は無視されているのでいいけど, 本来は,ヘルプにもあるように, CoClass(コクラス)のインターフェイスの方を,指定するのでなく, Interop(相互運用機能)が作成した ○○Class というクラスの方を指定しなさい となっているので,そのようにします。 それと,SHGetMallocでIMallocインターフェイスを取得する際に, シェル側でAddRefしてるので, こちらでReleaseしてやらないといけないんじゃないか?とか, でも,GetTypedObjectForIUnknownを使ってから, マーシャラが面倒見てくれる(Releaseしてくれる)んじゃないか? とか...どうなんだ??となって... ちゃんぽんにするとわけがわからなくなります。 なので, 上のやりとりで出た結論のように,COM相手の場合は,最初から, Marshal.AllocCoTaskMem (.FreeCoTaskMem) 等を使ったやりとりに限定した方が 危なげないというか,無難なような気がします。 Marshal.AllocHGlobal (.FreeHGlobal) の方は, インターフェイスとか,その参照カウントとかとは無縁な世界の時の 関数の引数のやりとりに使うためのものでしょう。 ※ CoClass(コクラス) COMのクラスには, タレントで言うところのマネージャに相当するオブジェクトが それぞれに専用に作ってあって, それを CoClass(コクラス) とか Class Object(クラス・オブジェクト)と言っています。 CoClassに対してインターフェイスを要求することで, CoClassを介して,COMオブジェクトを取得する仕組みになっています。 COMオブジェクトの寿命は,CoClassが管理しているので 直接やりとりしようと思うと結構大変なことになります。 [ メッセージ編集済み 編集者: 稍丼 編集日時 2005-12-23 16:08 ] | ||||||||||||||||||||||||
|
投稿日時: 2005-12-24 06:15
返信が適用されていない……
お二方、どうもありがとうございます、やはり揃えるというのが大事ですね。 あと、
の意味が良く分かりません(汗。インターフェイスを指定するなとその意味は大体つかめていると思うのですが「○○Class というクラスの方を指定しなさい」の意味が少し……よろしければもう少し詳しく教えていただけないでしょうか、申し訳ありません。 _________________ 9uiet Design - http://quietdesign.rental.allinoneserver.net/ デザインにこだわったソフトの配布とプログラミングTipsの公開(予定)をしています。 9uiet Blog - http://seiga.blog44.fc2.com/ 笑ったことやプログラミングのことなど書 | ||||||||||||||||||||||||
|
投稿日時: 2005-12-24 17:19
こんにちは。
なんだかMarshal.GetTypedObjectForIUnknownメソッドのMSDNの解説を見てみると、 第2引数の"Type t"って制約が多いんですね。
よく分からないですが…解説から推測するに たとえば、ExcelをCOM参照設定で追加した場合、 「ApplicationClassクラス」と「Applicationインターフェイス」が自動的に定義されますが、 【OK】Object o = Marshal.GetTypedObjectForIUnknown(ptrUnknown, typeof(ApplicationClass)); 【NG】Object o = Marshal.GetTypedObjectForIUnknown(ptrUnknown, typeof(Application)); ってことでしょうか。 でも、今回の場合おそらくIMallocインターフェイスは「タイプライブラリ インポータ」によって定義されたものではないですよね? この場合はどうすればいいんでしょうね? Marshal.GetTypedObjectForIUnknownではなくMarshal.GetObjectForIUnknownを使ったほうがいいんでしょうかね!?こんな感じで↓。 #キャスト部分がちょっと気持ち悪いですけれども…
ちょっと、話が変わりますが… (ご存知のこととは思いますが)よく混乱することがありますので… COMオブジェクトは”1つ以上の”インターフェイスを持ちます。 #1つはIUnknownインターフェイスであり、このIUnknownインターフェイスを実装することがCOMオブジェクトとしての必要条件です。 つまり、COMオブジェクトのクラス(CoClass)とそのインターフェイスは、「1対1」で対応していません。 それぞれにはGUIDという一意のIDが割り振られているのですが、 CoClassのIDは「CLSID」、インターフェイスのIDは「IID」と呼ばれます。 例えばExcel.ApplicationオブジェクトをよくあるCOMモデルで表現すると、 ”多分”こんな感じ↓でしょうか。(ちょっと自信はないですが…)
[ メッセージ編集済み 編集者: Tdnr_Sym 編集日時 2005-12-25 00:50 ] | ||||||||||||||||||||||||
|
投稿日時: 2005-12-25 09:16
# 余計なことを書いたのかもしれません。
GetObjectForIUnknown() の方には,
のように厳しいことを言っておきながら,
なんていう記述が,わざわざありますね(汗)。 で,あらためて,ヘルプを読み直すと... ツールを使うと, ○○Class という方は,CoClass起源で ○○ という方は,デフォルトインターフェイス起源 になるお約束になっているので, インスタンスを要求したい場合は,○○Class の方を指定しなさい... という意味で,その理由は, CoCreateInstance() が必要な時は,CoClass起源のマネージ型が必要になるから ○○Class を指定しないさい という意味なんでしょう。 VBからは,デフォルトのインターフェイスは見えないので, 指定しようがないので, C#固有の問題として書いてあるだけなのかもしれません。 で, > pUnk パラメータのオブジェクトが既に取得されている場合、 > t は無視され、既存のオブジェクトが返されます。 は,また別問題で, QueryInterface() に相当するような時なら, インターフェイス起源のマネージ型を指定してもいい... ということなのかもしれません。 なので,今回の場合は, インターフェイス起源の定義でOKでしたね。 ただ,
は良くても,直接,
は,もちろんダメなんですよね? だったら,
の方が,いい感じがしないでもないんだけど... [ メッセージ編集済み 編集者: 稍丼 編集日時 2005-12-25 09:20 ] |