2

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

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

不幸的是,尽管在将信息从 Native 组件传递到 C#/XAML 组件方面进行了一些平庸的尝试,但我没有取得太大进展,我感觉自己已经死了。

我将不胜感激任何有关这方面的指导。谢谢阅读。

4

5 回答 5

4

经过大量的探索(以及在这个线程中回答的一些人的帮助!)我能够找到这个解决方案:Calling C# method from C++ code in WP8

为了简单起见,我将在这里复制它:

在尝试找出所需的代码后,我认为值得在这里发布最终版本

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);
于 2013-06-30T21:39:22.133 回答
1

这是因为您无法将 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

于 2013-06-25T19:27:58.747 回答
1

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

例如在 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 和互操作服务,它可能会起作用,但不幸的是我没有测试过并且没有示例。

于 2013-06-25T20:23:40.617 回答
0

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

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

于 2013-06-26T01:23:23.747 回答
0

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

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

public delegate void SomeDelegate(Platform::String^ args);

public ref class Component sealed
{
  public:
  void SetDelegate(SomeDelegate^);

  private:
  Platform::Agile<SomeDelegate> 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/

于 2014-07-25T19:36:18.077 回答