背景を読みたくない場合は、「問題」ラベルに移動してください。
C++ から C# に関数を呼び出す方法を見つけるために、最初にこの質問を投稿しました: How do one make function calls or trigger events from a Native component into a C#/XAML component?
これは、回答としてマークされた解決策につながります。これは、友人がスタックオーバーフローを回避して機能することを確認しました。
次に、ソリューションの指示に従って、次の 2 つのコールバック クラスを実装しました。
// C++ land
// This is the interface that defines all of the functions
// that this component can call on the C#/xaml side
[Windows::Foundation::Metadata::WebHostHidden]
public interface class ICallback
{
public:
// begins the displaying of the progress bar and signals
// the start of a new task
virtual void BeginProgress(Platform::String ^ message);
// completes a the progress started by the progress bar and returns the
// result of the task done. Also has an optional message which can give
// the user additional information if failure occured.
virtual void CompleteProgress(int result, Platform::String ^ message);
};
// C# land
// used as a callback from the native component to here
// just delegates calls to the page
class Callback : ICallback
{
// a reference to the page so we can dispatch UI events
private ViewerPage m_page;
public Callback(ViewerPage page)
{
m_page = page;
}
// just delegates to the page
public void BeginProgress(String message)
{
m_page.BeginProgress(message);
}
public void CompleteProgress(int result, String message)
{
m_page.CompleteProgress(result, message);
}
}
// the page then handles those calls as you would expect
問題:
ネイティブ コンポーネントが次のように初期化されるときに、コールバックを設定します。
// ViewerPage.cs
private void DrawingSurfaceBackground_Loaded(object sender, RoutedEventArgs e)
{
if (m_d3dBackground == null)
{
m_d3dBackground = new Direct3DBackground();
// Set window bounds in dips
m_d3dBackground.WindowBounds = new Windows.Foundation.Size(
(float)Application.Current.Host.Content.ActualWidth,
(float)Application.Current.Host.Content.ActualHeight
);
... // more initialization stuff
// hook up the callback
m_d3dBackground.Callback = m_callback;
... // even more
}
}
次に、次のように m_d3dBackground から Renderer クラスにコールバックを渡します。
m_renderer->Initialize(Callback);
次に、レンダラーは次のように、適切な場合にコールバックを呼び出そうとします。
// let the user know we're starting the lengthiest one time operation of this application
// TODO: figure out the bug that keeps this from working
m_callback->BeginProgress("Loading Model");
これは、物事がうまくいかないときです。
Platform::NullReferenceException が発生します。呼び出されたポインターが、d3dBackground オブジェクトに渡された最初のポインターであることを確認できます。
例外発生時のスタック トレースを次に示します。
残念ながら、ほとんどのレコードは並行性について意味不明なので、あまり役に立ちません。
非常に問題のある m_callback を含むメンバー変数は次のとおりです。
最後に、NullPointerException が発生した場所のメモリ ダンプを次に示します (正確な場所が強調表示されています)。
私は本当にこれについて頭を悩ませているので、誰かが直感やヒントを持っているなら、私は大いに感謝します.
読んでくれてありがとう。