How does one make function calls or trigger events from a Native component into a C#/XAML component?

会有一股神秘感。 提交于 2019-12-06 08:09:08
Nico

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++.

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

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/

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!