アプリ版:「スタンプのみでお礼する」機能のリリースについて

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" を表示)
よろしくお願いします。

A 回答 (2件)

マーシャリングで調べて、この辺も参考になるかもしれません。


https://docs.microsoft.com/ja-jp/dotnet/framewor …
    • good
    • 0
この回答へのお礼

ありがとうございました。

調べてみます。

お礼日時:2020/09/10 23:04
    • good
    • 0
この回答へのお礼

ありがとうございました。

調べてみます。

お礼日時:2020/09/10 23:04

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!