c# - 当我尝试通过 WinRT 对象从 C++ 调用回调到 C# 时如何解决此 E_POINTER (NullPointerException)?

标签 c# c++ windows windows-phone-8 windows-runtime

如果您不想阅读背景,请转到“问题”标签。

我第一次发布这个问题是为了找到一种将函数从 C++ 调用到 C# 的方法:How does one make function calls or trigger events from a Native component into a C#/XAML component?

这导致了被标记为答案的解决方案,我已确认由一位 friend 解决了堆栈溢出问题。

然后我按照解决方案的说明实现了以下两个回调类:

// 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

问题:

我在初始化 native 组件时设置回调,如下所示:

// 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");

这是出了问题的时候。

Exception

我得到一个 Platform::NullReferenceException。我可以确认调用的指针仍然是传递到 d3dBackground 对象的第一个指针。

这是异常发生时的堆栈跟踪:

Stack Trace

不幸的是,大多数记录都是并发的乱码,所以这没什么帮助。

下面是成员变量,包括问题多多的m_callback:

Member Variables

最后,这是 NullPointerException 发生位置的内存转储(确切位置已突出显示):

Memory

我真的在为这个问题绞尽脑汁,所以如果有人有任何直觉或提示,我将不胜感激。

感谢阅读。

最佳答案

好吧,我在点击提交这篇文章后大约 3 分钟就解决了这个问题。

问题是回调对象的 C# 版本看起来并不像 C++ 编译器认为的那样 %100(根据 ICallback 的定义)。

问题是什么?对 ViewerPage 的引用与编译器认为 BeginProgress() 所在的内存位置相同。

解决方案?将 ICallback 实现移到 Page 类中,因为编译器会自动将成员变量移动到对象的开头,而不管它们在代码中的位置。

public partial class ViewerPage : PhoneApplicationPage
{
    private Callback m_callback;

    ... // rest of ViewPage class

    // used as a callback from the native component to here
    // just delegates calls to the page
    class Callback : ICallback
    {
        public Callback()
        {
        }

        // just delegates to the page
        public void BeginProgress(String message)
        {
            BeginProgress(message);
        }

        public void CompleteProgress(int result, String message)
        {
            CompleteProgress(result, message);
        }
    }
}

-.-

关于c# - 当我尝试通过 WinRT 对象从 C++ 调用回调到 C# 时如何解决此 E_POINTER (NullPointerException)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17477624/

相关文章:

c++ - Windows 2000 的 GetProcessID 的替代方法

c# - WPF在不同窗口中镜像网格内容

c# - 将复选框绑定(bind)到数据库中的位字段 (AJAX)

c# - WinForms Validating 事件阻止 Escape 键关闭表单

c# - 使用 Thread.Sleep 时启动 .NET Windows 服务时出现问题

c++ - 警告 : statement has no effect (C++)

c++ - 完全删除 vector C++

c++ - 如何为我的类(class)提供交换功能?

windows - 使用适用于 Windows 的 VBScript 刷新 Windows 任务栏?

python - 在 Python 中加载 dll 时出现 Windows 错误 1114