I am developing a WP8 application with a Native (DirectX/D3D) component and a C#/XAML component.
The Native component draws to a UI element and the C#/XAML component has the controls of the app (and other things) surrounding it. Usually, I send information from the C#/XAML component down to the Native component. But there are certain times when I would like to trigger events in the C#/XAML component based on when processing is done in the Native component. In one planned feature, I envision a C#/XAML progress bar that is kept up to date by events triggered in the Native component.
Unfortunately, despite some mediocre attempts to get information passed from the Native component to the C#/XAML one, I haven't made much progress and I feel dead in the water.
I would greatly appreciate any guidance on this. Thanks for reading.
After much poking around (and much help from some of the guys that answered in this thread!) I was able to find this solution: Calling C# method from C++ code in WP8
I will reproduce it here for simplicity's sake:
After a lot of headaches trying to figure out the required code, I think it's worth posting the final version here
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);
This is because your not able to have your C++ code call into C#. You can only have C# call (and return) into C++.
Something you can do is keep a function pointer to a function in C#. You can from C# call the native C++ to store the function pointer then you can call it whenever you want. The function as to be static.
for instance in 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;
}
and have in the constructor maybe
SetAchievementUnlocked( mAchievementUnlockCallBack );
then in C++
typedef int (*AchievementUnlockCallBack)(AchievementsType pType, char* pMessage);
AchievementUnlockCallBack globalCallback = NULL;
__declspec(dllexport) void SetAchievementUnlocked( AchievementUnlockCallBack callback )
{
globalCallback = callback
}
Then anywhere you have access to that variable you can do
void Achievement::Unlock()
{
if(globalCallback)
{
globalCallback(this->getType(), this->getName().c_str());
}
}
Hopefully this can help you. If you are not using dll and interops services, it probably would work, but I haven't tested and don't have examples unfortunatly.
The other way around is what works. You can call native code from C# (managed code) through COM interops: http://msdn.microsoft.com/en-us/library/aa645736%28v=VS.71%29.aspx
I don't think it is possible to call managed code from native. What are you trying to do?
You can pass a delegate from your C# to the C++ Component.
In your C++ Component you'll define a delegate and a method call to set that delegate, like this:
public delegate void SomeDelegate(Platform::String^ args);
public ref class Component sealed
{
public:
void SetDelegate(SomeDelegate^);
private:
Platform::Agile<SomeDelegate> m_delegate;
}
Then in your C# you can create a function that matches the delegate signature, and pass it down to your component:
public void DelegateFunction(string args)
{
// run C# code that was invoked from C++
}
// elsewhere in your C# code
component.SetDelegate(DelegateFunction);
Then in your C++ you can just invoke the delegate method whenever you need to.
Edit: I wrote a blog post about this topic - http://robwirving.com/2014/07/21/calling-c-methods-c-winrt-components/
来源:https://stackoverflow.com/questions/17304386/how-does-one-make-function-calls-or-trigger-events-from-a-native-component-into