MFCDLL内の関数をC#で呼び出す

過去の資産をC#で利用したい。
その基本的なやり方を示します。


MFCDLLのプロジェクトを作成し、
apiModule.cppを追加し下記のように記述します。
defファイルに関数名を記述します。

apiModule.cpp

#include "StdAfx.h"

void WINAPI Dll_ShowMessage(const CString &str)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());

	::AfxMessageBox(str);

	return;
}

void WINAPI Dll_ShowInt(int num)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());

	CString str;
	str.Format(_T("%d\n"), num);
	::AfxMessageBox(str);
}

defファイル

; mfcDllTest.def : DLL のモジュール パラメータを宣言します。

LIBRARY      "mfcDllTest"

EXPORTS
    ; 明示的なエクスポートはここへ記述できます
Dll_ShowMessage
Dll_ShowInt

これでビルドすると普通にdllが作成されます。
ただ、ユニコードでビルドしたのかマルチバイトでビルド
したのか気に留めておく必要があります。


次はC#での呼び出し方を示します。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using System.Runtime.InteropServices;

namespace dllImportTest {
	public partial class TestForm : Form {
		public TestForm()
		{
			InitializeComponent();
		}

		[DllImport("mfcDllTest.dll", CharSet=CharSet.Auto)]
		private extern static void Dll_ShowMessage(ref string str);

		[DllImport("mfcDllTest.dll", CharSet=CharSet.Auto)]
		private extern static void Dll_ShowInt(int num);

		private void button1_Click(object sender, EventArgs e)
		{
			string str = "test";
			Dll_ShowMessage(ref str);
			Dll_ShowInt(10);
		}
	}
}

"CharSet=CharSet.Auto"をつけていないと、
C#側でユニコードをマルチバイトにデフォルトで変換してしまいます。
C#側でも、MFCDLL側でもユニコードだから問題ないかなと
思い込んでいたら見事に嵌りました。


参照
http://www.atmarkit.co.jp/fdotnet/dotnettips/025w32string/w32string.html