在WP8中从C++代码调用C#方法

14
我想在Windows Phone 8中从C++代码调用C#方法。我已经学会了通过委托声明从C#向C++代码传递回调函数,但我想知道以下几点是否可行:
  • 直接从C++代码调用某些方法。这需要以某种方式从C++中检查C#对象构成,这似乎不太可能,但我还是想问问大家。

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

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

  • 使用调度程序触发C#代码中的事件(本质上是以上两个点的合并)

简而言之,我正在寻找尽可能多的C++ -> C#通信技巧,我想学到所有的内容。 :)
2个回答

20
通过在C#代码中让一个对象实现Windows RT接口,并传递对该对象的引用,可以通过一些设置来完成上述所有操作(如果我理解正确-关于你想要使用Dispatcher示例做什么,我不太确定-你可能想在C#端包装Dispatcher)。
  1. 创建一个Windows Runtime组件库。
  2. 在C++/CX头文件中定义一个公共接口类供C#实现(C++调用)(例如ICallback)。
  3. 在C++/CX头文件中定义一个公共ref类供C++实现(C#调用)(例如CppCxClass)。
  4. 在CppCxClass中添加一个方法,将ICallback传递并存储起来。(为简洁起见,此处显示了一个C++全局变量,建议您查看其是否可以在代码库中找到更好的存储位置。)
  5. ICallback^ globalCallback;
    ...
    void CppCxClass::SetCallback(ICallback ^callback)
    {
        globalCallback = callback;
    }
    
  6. 在C#代码中引用WinRT库。

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

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


太好了!这几乎回答了我所有的问题!最后一个问题是,我是否可以使用类似于C#中的Dispatcher,以便这些回调可以在主UI线程内被调用。 - staticfloat
找到一个 Dispatcher 的解决方案:https://dev59.com/8Gkv5IYBdhLWcg3wdQnm - staticfloat
非常感谢!我一直在寻找这种回调技术,但在其他地方都没有找到合适的描述。 - Moshe Kravchik
也许我是一个 C# 新手,但是 ICallback 需要哪个命名空间? - RelativeGames
这是一个完整的实现和演示:http://www.developer.nokia.com/Community/Wiki/Writing_interfaces_that_can_be_implemented_by_both_Native_and_Managed_classes。 - Berthier Lemieux
我不明白。当在C++中启动程序时,C#类实例从哪里来?或者说你如何在C++中实例化一个C#类? - Gerold Meisinger

16

经过很多头疼的尝试来找出所需的代码,我认为将最终版本发布在这里是值得的。

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

7
当然,因为这样一个像我这样有同样问题的家伙会出现,而你能够节省我大量的时间。谢谢你。 - Nico
如果您能回答相关的SO问题@http://stackoverflow.com/questions/23872394/calling-c-sharp-function-from-win-rt-library,那就太好了。 - Arctic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接