バックグラウンド スレッドでいくつかのタスクを実行するための単純な API を持つ C# 相互運用機能を介して C++ ライブラリを利用しています。問題は、バックグラウンド タスクを実行する C++ 関数がヌル ポインターを受け取り、バックグラウンド タスクの実行中にヌル ポインターが「埋められる」ことです。また、スレッド化は C# 側で行われるため、オブジェクトのみをパラメータとして受け取る「ParameterizedThreadStart」デリゲート タイプを使用する必要があります。次に、C# コードからそのオブジェクトにアクセスする必要があります。以下のスニペットが私の言いたいことを説明できることを願っています。
C++:
extern "C" void __declspec(dllexport) performLongTask(MyClass** myObject)
{
myObject = new MyClass;
// Time-consuming operation...
}
C#:
[DllImport("myDllName")]
public static extern void performLongTask(ref IntPtr myObject);
// Ugly, but necessary for ParameterizedThreadStart delegate?
unsafe class PtrWrapper
{
public IntPtr Pointer = new IntPtr();
}
public static unsafe performLongTask_paramThreadStartWrapper(object arg)
{
PtrWrapper ptrWrapper = (PtrWrapper)arg;
performLongTask(ref ptrWrapper.Pointer);
}
public static unsafe void DoInteropStuff()
{
PtrWrapper ptrWrapper = new PtrWrapper();
Thread bgThread = new Thread(new ParameterizedThreadStart(performLongTask_paramThreadStartWrapper));
bgThread.Start(ptrWrapper);
// Wait a little while, let background thread processing go....
// Use pointer to retrieve some stuff from other unmanaged code
if(ptrWrapper.Pointer != IntPtr.Zero)
object currentData = getData(ptrWrapper.Pointer);
}
この結果、マネージ側で作成した IntPtr は、アンマネージ コードが正常に実行されているように見えるにもかかわらず、決して変更されません (debug print ステートメントは、物事が期待どおりに進んでおり、ポインターが確実に設定されていることを示しています)。管理されていない側)。
私はそれが最もきれいなコードではないことを知っています。おそらく、この全体をきれいにするいくつかの方法があります。私はいくつかのことに興味があります:
1.) C++ ライブラリをそのまま使用してこれを実現する最善の方法 (アンマネージ コードを変更しない)。
2.) このコードが機能しないのはなぜですか? それは醜いですが、ポインタが正しく渡されていると思うので、うまくいくはずです...
ご協力いただきありがとうございます!