C#からC言語で書かれたDLLを呼び出す

自前で作ったBase64エンコードとデコードを行うプログラムをC#側で使おうと思って調べてみた。
(なお、単に文字列をBase64エンコードするだけなら Convert.ToBase64String メソッドを使えば一発ですのでこんなことする必要はありません)

まず、DLL側のC言語ヘッダファイルを確認。

__declspec(dllexport) 
 int EncodeBase64Size(const int inLen, const int inCRLF);
__declspec(dllexport)
 void EncodeBase64(const char* inStr, const int inLen, char *outStr, const int inCRLF);

__declspec(dllexport) がついていれば外部から呼出し可能になります。

そして呼び出すC#側は、
[DllImport("Base64.dll", CallingConvention = CallingConvention.Cdecl)]
 public static extern int EncodeBase64Size(int inLen, int inCRLF);
 [DllImport("Base64.dll", CallingConvention = CallingConvention.Cdecl)]
 public static extern void EncodeBase64(string inStr, int inStrLen, StringBuilder outStr, int inCRLF);
というメソッドを追加します。

"Base64.dll"が使いたいDLL名、CallingConvention = CallingConvention.Cdecl は、.NET3.5以降でPInvokeStackImbalance 例外が発生するのでそれを回避する為に入れます。 詳細は「PInvokeStackImbalance が検出されました」って何だ? と MeCab を参照。

そしてDLLの引数とC#の型を合わせること。
int型はそのままint型で良いが、アドレス渡しの場合はちょっと工夫がいる。
char[]の先頭アドレスを渡す場合、StringBuilderクラスを使うようです。
StringBuilderを使う場合、予め十分なサイズを確保しておく必要があります。
詳細は.NET TIPS Win32 API や DLL 関数を呼び出すには? - @ITを参照してください。
そして呼び出す処理を追加する。

 private void button1_Click(object sender, EventArgs e)
 {
  StringBuilder sb;
  int length = EncodeBase64Size(textBox1.Text.Length, 76);
  sb = new StringBuilder(length);
  EncodeBase64(textBox1.Text, textBox1.Text.Length, sb, 76);
  textBox2.Text = sb.ToString();
 }

実際に動作確認。
DLLをプログラムと同じフォルダに置いて実行する。

こんなかんじで使えます。

0 件のコメント: