私は最近、C#とC ++の相互運用機能をいじくり回しており、特にC++DLLから呼び出されるコールバック関数を設定しています。
namespace TomCSharpDLLImport
{
class Program
{
public delegate void TomDelegate(int a, int b);
[DllImport("TomDllNative.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void GetData();
[DllImport("TomDllNative.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void SetCallback(TomDelegate aCallback);
static void Main(string[] args)
{
TomDelegate lTD = new TomDelegate(Program.TomCallback);
SetCallback(lTD); //Sets up the callback
int thread = Thread.CurrentThread.ManagedThreadId;
GetData(); //This calls the callback in unmanaged code
while (true) ;
}
//Callback function which is called from the unmanaged code
public static void TomCallback(int a, int b)
{
Console.WriteLine("A: {0} B: {1}", a, b);
int thread = Thread.CurrentThread.ManagedThreadId;
}
}
}
私が持っている質問は、プログラムコントロールがTomCallback関数に入るとき、それがMainのwhile(true)ループにヒットすることを期待していたということです。ただし、代わりにプログラムは終了します。私はその行動に頭を悩ませることはできません。私の一部はこれが予想通りであると想像していますが、私の一部はそれが主に続くことを期待していたでしょう。
私が期待していたこと...
- GetData()関数が呼び出されます
- GetData関数はコールバックを呼び出します
- コールバック関数はGetDataに戻ります
- GetDataはmain()に戻ります
しかし、これは完全に正しくありません。
誰かが何が起こるかを説明するのに十分親切でしょうか。
スペースを節約するために、アンマネージコードは投稿していませんが、必要に応じて投稿できます。
編集: アンマネージデバッグをオンにしました(これを行うのを完全に忘れました)。クラッシュが表示されます。
実行時チェックの失敗#0-ESPの値は、関数呼び出し全体で適切に保存されませんでした。これは通常、ある呼び出し規約で宣言された関数を、別の呼び出し規約で宣言された関数ポインターで呼び出した結果です。
これはクラッシュが発生する場所であるため、ネイティブコード
#include "stdafx.h"
typedef void (*callback_function)(int, int);
extern "C" __declspec(dllexport) void SetCallback(callback_function aCallback);
extern "C" __declspec(dllexport) void GetData();
callback_function gCBF;
__declspec(dllexport) void SetCallback(callback_function aCallback)
{
gCBF = aCallback;
}
__declspec(dllexport) void GetData()
{
gCBF(1, 2);
}