【问题标题】:Calling C# method from C++ code in WP8在 WP8 中从 C++ 代码调用 C# 方法
【发布时间】:2025-12-27 05:55:12
【问题描述】:

我有兴趣从 Windows Phone 8 中的 C++ 代码调用 C# 方法。我已经学会了如何通过我的 C++ 代码中的委托声明将回调函数从 C# 传递给 C++ 代码,但我想看看是否我可以执行以下任何操作:

  • 直接从 C++ 代码调用某些方法。这将涉及以某种方式检查 C++ 中的 C# 对象构成,这对我来说似乎不太可能,但我想我还是会问大家

  • 在 C# 代码中触发事件,然后可以由 C# 方法处理

  • 在主 UI 线程中使用调度程序调用 C# 回调,以便回调可以修改 UI 元素

  • 在C#代码中使用dispatcher触发事件,(本质上是以上两点的合并)

简而言之,我正在寻找尽可能多的 C++ -->C# 通信技巧,你们可以给我,我想全部学习。 :)

【问题讨论】:

    标签: windows-phone-8 c++-cx


    【解决方案1】:

    通过在 C# 代码中获取一个对象来实现 Windows RT 接口,并传递对该对象的引用,可以通过一些设置来完成上述所有操作(如果我理解正确 - 不确定关于你想用你的 Dispatcher 示例做什么——你可能想在 C# 端包装 Dispatcher)。

    1. 创建一个 Windows 运行时组件库。
    2. 在 C++/CX 标头中定义 public interface class 以供 C# 实现(C++ 调用)(例如 ICallback)。
    3. 在 C++/CX 标头中定义 public ref class 以供 C++ 实现(C# 调用)(例如 CppCxClass)。
    4. CppCxClass 中添加一个传递并存储ICallback 的方法。 (为了简洁起见,显示了一个 C++ 全局变量,我建议您查看此内容,看看您是否可以找到更好的位置将其存储在您的代码库中)。

      ICallback^ globalCallback;
      ...
      void CppCxClass::SetCallback(ICallback ^callback)
      {
          globalCallback = callback;
      }
      
    5. 在 C# 代码中引用 WinRT 库。

    6. C# 代码:使用var cppObject = new CppCxClass() 创建CppCxClass 的实例。
    7. C# 代码:创建一个实现ICallback 的类(例如CSharpCallbackObject)。
    8. C# 代码:将 CSharpCallbackObject 的实例向下传递给 C++。例如。 cppObject.SetCallback(new CSharpCallbackObject())

    您现在可以使用 globalCallback->CallCsharp(L"Hello C#"); 调用 C#。您应该能够扩展 ICallback 和/或 CppCxObject 以完成其余任务。

    【讨论】:

    • 太棒了!这几乎回答了我所有的问题!最后一点是,如果我可以像在 C# 中那样使用某种 Dispatcher,以便可以在主 UI 线程中调用这些回调。
    • 找到了 Dispatcher 问题的解决方案:*.com/questions/10579027/…
    • 非常感谢!我一直在寻找这种回调技术,但在其他任何地方都找不到它的正确描述
    • 也许我是 C# 菜鸟,但 ICallback 需要的命名空间是什么?
    • 此解决方案的完整实现+演练:developer.nokia.com/Community/Wiki/…
    【解决方案2】:

    在费了很多力气想出所需的代码之后,我认为值得在这里发布最终版本

    C++/CX

    //.h
    [Windows::Foundation::Metadata::WebHostHidden]
    public interface class ICallback
    {
    public:
        virtual void Exec( Platform::String ^Command, Platform::String ^Param);
    };
    //.cpp
    ICallback ^CSCallback = nullptr;
    void Direct3DInterop::SetCallback( ICallback ^Callback)
    {
        CSCallback = Callback;
    }
    //...
    
    if (CSCallback != nullptr)
        CSCallback->Exec( "Command", "Param" );
    

    C#

    public class CallbackImpl : ICallback
    {
        public void Exec(String Command, String Param)
        {
            //Execute some C# code, if you call UI stuff you will need to call this too
            //Deployment.Current.Dispatcher.BeginInvoke(() => { 
            // //Lambda code
            //}
        }
    }
    //...
    CallbackImpl CI = new CallbackImpl();
    D3DComponent.SetCallback( CI);
    

    【讨论】:

    • 肯定是这样,因为像我这样的人会遇到同样的问题,而您为我节省了大量时间。谢谢。
    • 如果能回答相关的SO问题就太好了@*.com/questions/23872394/…