在Windows Phone 8的開發過程中,特別是游戲開發過程中,WP8 SDK提供的工程模版Windows Phone XAML and Direct3D App是一個不錯的選擇。該工程采用C++和C#的混合編程模式,由一個C++編寫的WinRT組件和一個C#項目組成,其中WinRT組件基於Direct3D編寫,負責幾乎所有的游戲邏輯,而C#則負責Windows Phone常規控件和頁面邏輯,並提供一個DrawingSurface來處理游戲組件的事務。這種開發模式為游戲開發者節省了大批時間和精力。
做過Windows Phone 7的開發者都知道,以前很多業務邏輯都是通過編寫C#的類庫進行封裝並重復使用,但是到了Windows Phone 8,假如還想繼續使用這類C#類庫,並且需要在C++的代碼中調用C#類庫的接口時怎么辦?
直接在C++工程里引用C#類庫是不行的,你會得到下面的錯誤:
以下解決方案將徹底解決這個難題,以解決在D3D游戲邏輯中向OpenXLive提交分數為例子。
1. 首先默認你已經創建好了Windows Phone XAML and Direct3D App工程,並且在C#項目里面引用已有的C#類庫,比如OpenXLive.dll
2. 在WinRT組件中(C++)創建一個符合WinRT編程規范的接口ICallback,暴露給C#實現
創建一個ICallback.h文件:
namespace OpenXLiveSLDirect3DtTemplateComp { namespace OpenXLiveHelper { // A callback interface for C# code to implement. public interface class ICallback { } } }
3. 在WinRT組件中(C++)創建一個符合WinRT編程規范的類,用來傳遞和存儲一個ICallback對象
創建XLiveDelegate.h文件和XLiveDelegate.cpp文件,在頭文件中定義一個SetCallback方法:
#include "ICallback.h" namespace OpenXLiveSLDirect3DtTemplateComp { namespace OpenXLiveHelper { // A native class to pass and store an ICallback instance, // calling C# code via the ICallback object. public ref class XLiveDelegate sealed { public: XLiveDelegate(); void SetCallback(ICallback^ callback); property static ICallback^ GlobalCallback; }; } }
其中,SetCallback將傳遞的ICallback對象保存在XLiveDelegate中:
void XLiveDelegate::SetCallback(ICallback^ callback) { GlobalCallback = callback; }
4. 在C#項目里面創建一個類實現WinRT組件暴露出來的接口ICallback
創建一個XLiveCallback.cs文件:
namespace OpenXLiveSLDirect3DtTemplate { /// <summary> /// A callback class that implements the WinRT Component interface ICallback. /// All methods provided will be called throught the ICallback interface in native code. /// </summary> public class XLiveCallback : ICallback { } }
5. 在C#項目中創建一個XLiveDelegate對象,並將一個XLiveCallback對象傳遞回C++代碼
XLiveDelegate m_XLiveDelegate = new XLiveDelegate(); m_XLiveDelegate.SetCallback(new XLiveCallback());
6. 在WinRT組件中(C++)的ICallback接口中,提供一個提交分數的方法
public interface class ICallback { void Leaderboard_Submit(Platform::String^ leaderboardKey, int score); }
7. 在XliveCallback類中實現這個方法,這個方法調用已有C#類庫的方法
public class XLiveCallback : ICallback { public void Leaderboard_Submit(string leaderboardKey, int score) { Leaderboard lb = new Leaderboard(XLiveGameManager.CurrentSession, leaderboardKey); lb.SubmitScoreCompleted += lb_SubmitScoreCompleted; lb.SubmitScore(score); } }
其中Leaderboard類就是OpenXLive.dll的具體方法。
8. Direct3D的游戲邏輯中,通過調用XLiveDelegate->GlobalCallback-> Leaderboard_Submit來間接調用C#類庫的方法!
XLiveDelegate^ m_XLiveDelegate = ref new XLiveDelegate(); m_XLiveDelegate->GlobalCallback->Leaderboard_Submit("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 100);