最新の更新情報

2012年2月
« 1月    
 1234
567891011
12131415161718
19202122232425
26272829  

本ブログのURL

qrcode.png

雨雲の動き

お天気

 
 
吟遊詩人の戯言 内専用の記事検索...
 
 

C#&32bitアンマネージDLL/64bitアンマネージDLLの動的な呼び出し方法


キーワード(クリックで関連記事が読めます) →

関連記事



 
 

Windows7の登場で
64ビット環境が,すさまじい勢いで普及しておりますです...

して,Windowsの32ビットアプリ,64ビットアプリには掟がありまして

32ビットのEXEは,32ビットのDLL
64ビットのEXEは,64ビットのDLL

しか,呼べないことになっております.交差して呼び出すことは現状,仕様で出来ません

そこで,登場する,C#で作ったアプリ(マネージアプリ)
C#やら,VB.NETやらで作成したアプリは,インストールした環境にて,JITコンパイラが,最終コンパイルしてくれます

Windowsが32ビットだったら,32ビットアプリに
Windowsが64ビットだったら,64ビットアプリに

コンパイルします

ただ,最終コンパイルしたEXEが,アンマネージ(VCあたりで作った)なDLLを呼んでいる場合は,問題が生じますです

マネージ側が64ビットにJITコンパイルしてくれても,アンマネージDLLは32ビットのまま
上の方に書いた法則が発動して,BadImageFormatExceptionなエラーが発生となります

ってことで,環境に依存せず,BadImageFormatExceptionエラーを出さないような,Exe~DLLの呼び出し方法をちょいと書いてみました



1.まずは,32ビットと64ビットのDLLをVC++で作成しましょう

MSDNに64ビットなアプリの作り方が書いてあります

作成したDLLは,
    32ビット:hogehoge.dll
    64ビット:hogehoge64.dll
と,DLLの名称を変えておきます

VC++のコードは,32/64ビットでコード変更はないはずです

2.C#(あるいはVB.NET)でDLLを呼び出すコードを書きます
こんな感じ
C#:
  1. #region 32bitDLL のAPI定義
  2. [DllImport("hogehoge.dll", EntryPoint="dll_TestFunc")]
  3. private static extern int dll_TestFunc32(int frameno, IntPtr ary, int aryCount);
  4. #endregion
  5.  
  6. #region 64bitDLL のAPI定義
  7. [DllImport("hogehoge64.dll", EntryPoint="dll_TestFunc")]
  8. private static extern int dll_TestFunc64(int frameno, IntPtr ary, int aryCount);
  9. #endregion
  10.  
  11. public int TestFunc(int frameno, ref float[] ary)
  12. {
  13.     int len = ary.Length;
  14.     GCHandle gcH = GCHandle.Alloc(ary, GCHandleType.Pinned);
  15.     int re;
  16.  
  17.     if (IntPtr.Size == 4)      //IntPtrのサイズで 32ビット環境か64ビット環境か調べる
  18.     {
  19.         re = dll_TestFunc32(frameno,    gcH.AddrOfPinnedObject(), len);  //32ビットのDLL呼び出し
  20.     }
  21.     else
  22.     {
  23.         re = dll_TestFunc64(frameno,    gcH.AddrOfPinnedObject(), len);  //64ビットのDLL呼び出し
  24.     }
  25.  
  26.     gcH.Free();
  27.     return re;
  28. }


DllImport命令のEntryPoint属性を使用し
32ビットDLL/64ビットDLLで,同一API名を別名付けて管理します

また,IntPtrのサイズを見て,現在の実行環境が32ビット/64ビットなのか,判断して
別名つけたAPIを呼び出します

3.(2)で作ったマネージなExeと同一フォルダに,この2つのDLLを置きます

こんな感じ
C#:
  1. //  host.exe(C#で作ったマネージなExe)
  2. //      |
  3. //      +--- hogehoge.dll(VC++で作ったアンマネージな32ビットDLL)
  4. //      |
  5. //      +--- hogehoge64.dll(VC++で作ったアンマネージな64ビットDLL)


32ビットWindows
64ビットWindows

どっちの環境に,このまんま,コピペしても問題なく動くはずです


これで,32ビット/64ビット過渡期時代も生き残れますわん ;-)

 
 
 
 

コメントを残す

  

  

  

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <img localsrc="" alt="">