如何从Native组件进行函数调用或触发事件到C#/ XAML组件?

我正在开发一个带有Native(DirectX / D3D)组件和C#/ XAML组件的WP8应用程序。

Native组件绘制到UI元素,C#/ XAML组件具有围绕它的app(和其他东西)的控件。 通常,我将信息从C#/ XAML组件发送到Native组件。 但是有些时候我想根据在Native组件中完成处理的时间来触发C#/ XAML组件中的事件。 在一个计划的function中,我设想了一个C#/ XAML进度条,它通过Native组件中触发的事件保持最新。

不幸的是,尽管有一些平庸的尝试将信息从Native组件传递到C#/ XAML,但我没有取得太大进展,我感到死在水中。

我非常感谢任何指导。 谢谢阅读。

经过多次讨论(以及在这个post中回答的一些人的帮助!)我能够找到这个解决方案: 从WP8中的C ++代码调用C#方法

为简单起见,我会在这里重现它:

在经历了很多令人头疼的问题之后,我认为值得在这里发布最终版本

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

这是因为您无法将C ++代码调用到C#中。 你只能将C#调用(并返回)到C ++中。

http://social.msdn.microsoft.com/Forums/wpapps/en-us/a850b680-6052-41c5-825a-d764d3369fe9/calling-c-code-from-c-in-windows-phone-8

你可以做的就是在C#中保存一个函数指针。 您可以从C#调用本机C ++来存储函数指针,然后您可以随时调用它。 该function是静态的。

例如在C#中

 [DllImport( @"SomeDLL.dll" )] static extern void SetAchievementUnlocked( AchievementUnlockCallBack callback ); public delegate int AchievementUnlockCallBack( AchievementsType id, IntPtr message ); static AchievementUnlockCallBack mAchievementUnlockCallBack = AchievementUnlocked; static int AchievementUnlocked( AchievementsType id, IntPtr pMessage ) { string achievementName = Marshal.PtrToStringAnsi( pMessage ); DisplayAchievement( achievementName ); MainWindowHandler.Context.Focus(); return 1; } 

也许在构造函数中

 SetAchievementUnlocked( mAchievementUnlockCallBack ); 

然后在C ++中

 typedef int (*AchievementUnlockCallBack)(AchievementsType pType, char* pMessage); AchievementUnlockCallBack globalCallback = NULL; __declspec(dllexport) void SetAchievementUnlocked( AchievementUnlockCallBack callback ) { globalCallback = callback } 

然后,您可以访问该变量的任何地方

 void Achievement::Unlock() { if(globalCallback) { globalCallback(this->getType(), this->getName().c_str()); } } 

希望这可以帮助你。 如果你不使用DLL和interops服务,它可能会工作,但我没有测试,并没有不幸的例子。

另一种方式是有效的。 您可以通过COM interop从C#(托管代码)调用本机代码: http : //msdn.microsoft.com/en-us/library/aa645736%28v=VS.71%29.aspx

我不认为可以从本机调用托管代码。 你想做什么?

您可以将C#中的委托传递给C ++组件。

在C ++组件中,您将定义委托和方法调用来设置该委托,如下所示:

 public delegate void SomeDelegate(Platform::String^ args); public ref class Component sealed { public: void SetDelegate(SomeDelegate^); private: Platform::Agile m_delegate; } 

然后在您的C#中,您可以创建一个与委托签名匹配的函数,并将其传递给您的组件:

 public void DelegateFunction(string args) { // run C# code that was invoked from C++ } // elsewhere in your C# code component.SetDelegate(DelegateFunction); 

然后在您的C ++中,您可以随时调用委托方法。

编辑:我写了一篇关于这个主题的博客文章 – http://robwirving.com/2014/07/21/calling-c-methods-c-winrt-components/