C#から、C++作成dll内の関数を呼び出す方法
C#から、C++で作成したdll内の関数を呼び出す方法は、以下の方法で実現できました。(メッセージボックスで "10" が表示されました)
[C++側のヘッダファイル]
#ifdef CPPDLL_EXPORTS
#define CPPDLL_API __declspec(dllexport)
#else
#define CPPDLL_API __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
CPPDLL_API int fnCppDll();
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
[C++側のソースファイル]
CPPDLL_API int fnCppDll()
{
return 10;
}
[C#側]
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
[DllImport("CppDll.dll")]
public static extern int fnCppDll();
public Form1()
{
InitializeComponent();
}
private void buttonGo_Click(object sender, EventArgs e)
{
int n = fnCppDll();
MessageBox.Show(n.ToString());
}
}
}
今回お聞きしたいのは、int型ではなく、C++側で型を定義されたクラスのオブジェクト(の参照)を返す関数を、C#側から呼び出し、それをどうやってC#で受け取るかを教えていただきたいのです。
具体的には以下のように実装してみました。
[C++側のヘッダファイル]
#ifdef CPPDLL_EXPORTS
#define CPPDLL_API __declspec(dllexport)
#else
#define CPPDLL_API __declspec(dllimport)
#endif
class CPPDLL_API CCppDll
{
public:
int data;
CCppDll(void);
};
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
CPPDLL_API CCppDll& fnCppDll(); // C#が参照渡しということで、参照を返すようにした。
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
[C++側のソースファイル]
CPPDLL_API CCppDll& fnCppDll()
{
CCppDll* a = new CCppDll();
return *a;
}
CCppDll::CCppDll() : data(11) // メンバーは 11 で初期化
{
}
[C#側]
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsApp1
{
// ビルドエラーが起きるないように、とりあえず、C++と同じ(ような)クラスを定義
public class CCppDll
{
public int data;
}
public partial class Form1 : Form
{
[DllImport("CppDll.dll")]
public static extern CCppDll fnCppDll();
public Form1()
{
InitializeComponent();
}
private void buttonGo_Click(object sender, EventArgs e)
{
int n;
CCppDll cls = fnCppDll(); // ※
n = cls.data;
MessageBox.Show(n.ToString());
}
private void buttonCancel_Click(object sender, EventArgs e)
{
Close();
}
}
}
実装しながらも、「これじゃあ、ダメだろうな。いかにもダメだな」と思った通り、上の※の部分で以下の例外が発生しました。
------- 例外(ここから) -------
マネージド デバッグ アシスタント 'FatalExecutionEngineError' : 'ランタイムの重大なエラーが発生しました。エラーのアドレスは 0xcc9ff5a2、スレッド 0x36c8 です。エラー コードは 0xc0000005 です。これは CLR のバグであるか、またはユーザー コードのアンセーフまたは確認不可能な部分にバグがある可能性があります。このバグの一般的な原因には、スタックが壊れる可能性のある COM-interop または PInvoke のユーザー マーシャリング エラーが含まれています。'
------- 例外(ここまで) -------
明らかに基本的なことが分かっていないことから起因するエラーと思われますが、具体的にどう実装すれば、正常に動きますか。(メッセージボックスで "11" を表示)
よろしくお願いします。