鉴于诺基亚(微软移动这个没人用的手机)开发者比较少,cocos2dx移植方面更是少的问题,总结一下WP8移植方面的资料,希望对大家有用,自己也当作笔记留念。
1、WP8方面有两种方式创建项目,HelloCpp和TestCpp就是这样,XAML方式和纯c++方式。最好选择xaml方式,因为你有可能会c++和c#进行交互。废话不说,有图有真相。
2、说到c++和c#交互,其实叫C++/CX(C++/CX其实是微软在Win8开发平台下,对C++语言的一种扩展),下面就讲述其用法,概念可以去百度。
a) c++调用c#,比如我想获得该诺基亚的UniqueID,直接上代码吧,了解c#委托的童鞋应该不难理解,if...baidu...
**************************************************************************** //WP8DataManager.h #ifndef __WP8DataManager_H__ #define __WP8DataManager_H__ namespace PhoneDirect3DXamlAppComponent { public delegate Platform::String^ GetUniqueIDDelegate(); public ref class WP8DataManager sealed { public: WP8DataManager(void) { } ///DeviceInfo //此方法将在c#中调用 void SetGetUniqueIDDelegate(GetUniqueIDDelegate^ del) { m_getUniqueIDDelegate = del; } //获得的id,c++直接调用 Platform::String^ GetUniqueID() { if(m_getUniqueIDDelegate) { return m_getUniqueIDDelegate->Invoke(); } return ""; } ///DeviceInfo end private: property static GetUniqueIDDelegate^ m_getUniqueIDDelegate; }; } #endif // __WP8DataManager_H__ **************************************************************************** //MainPage.xaml.cs namespace PhoneDirect3DXamlAppInterop { public partial class MainPage : PhoneApplicationPage { // other demo... //datamanager private WP8DataManager m_dataManager = null; private void DrawingSurface_Loaded(object sender, RoutedEventArgs e) { if (m_d3dInterop == null) { //demo ...... } if (m_dataManager == null) { m_dataManager = new WP8DataManager(); m_dataManager.SetGetUniqueIDDelegate(getUniqueID); } } public String getUniqueID() { /*try { byte[] uniqueIDbytes = (byte[])DeviceExtendedProperties.GetValue("DeviceUniqueId"); string uniqueID = System.Convert.ToBase64String(uniqueIDbytes); }catch(Exception ex){ MessageBox.Show(ex.Message, "Failed", MessageBoxButton.OK); }*/ return "abc"; } } } **************************************************************************** //your cpp demo PhoneDirect3DXamlAppComponent::WP8DataManager^ manager = ref new PhoneDirect3DXamlAppComponent::WP8DataManager(); Platform::String^ id = manager->GetUniqueID(); ****************************************************************************
b) c#调用c++,比如自己添加了一个EditBox和一个Button,通过代码将EditBox中的值返回给c++中,详见Demo,我的例子是输入一个兑换码然后返回给c++部分
**************************************************************************** //MainPage.xaml.cs //此处为c#调用,当button按键触发时 m_d3dInterop.OnWP8RedeemResult(WP8RedeemEventType.WP8RedeemSuccess,"110"); **************************************************************************** //Direct3DInterop.h void OnWP8RedeemResult(WP8RedeemEventType type,Platform::String^ code); //Direct3DInterop.cpp void Direct3DInterop::OnWP8RedeemResult(WP8RedeemEventType type,Platform::String^ code) { std::lock_guard<std::mutex> guard(mMutex); std::shared_ptr<WP8RedeemEvent> e(new WP8RedeemEvent(type,code)); mInputEvents.push(e); } **************************************************************************** //WP8DataEvent.h #ifndef __WP8DATA_EVENT__ #define __WP8DATA_EVENT__ #include <agile.h> #include "../InputEvent.h" ref class Cocos2dRenderer; namespace PhoneDirect3DXamlAppComponent { public enum class WP8RedeemEventType{ WP8RedeemFailed, WP8RedeemSuccess }; class WP8RedeemEvent: public InputEvent { public: WP8RedeemEvent(WP8RedeemEventType type,Platform::String^ code); WP8RedeemEvent(WP8RedeemEventType type); virtual void execute(Cocos2dRenderer ^ renderer); private: Platform::Agile<Platform::String> m_code; WP8RedeemEventType m_type; }; } #endif // #ifndef __WP8DATA_EVENT__ **************************************************************************** //WP8DataEvent.cpp #include "WP8DataEvent.h" #include "../Cocos2dRenderer.h" namespace PhoneDirect3DXamlAppComponent { WP8RedeemEvent::WP8RedeemEvent(WP8RedeemEventType type,Platform::String^ code) :m_type(type),m_code(code) { } WP8RedeemEvent::WP8RedeemEvent(WP8RedeemEventType type) :m_type(type) { } void WP8RedeemEvent::execute(Cocos2dRenderer ^ renderer) { switch(m_type) { case WP8RedeemEventType::WP8RedeemSuccess: renderer->nativeRedeemSuccess(m_code.Get()); break; case WP8RedeemEventType::WP8RedeemFailed: renderer->nativeRedeemFailed(); break; default: break; } } } **************************************************************************** //Cocos2dRenderer.h void nativeRedeemFailed(); void nativeRedeemSuccess(Platform::String^ code); //Cocos2dRenderer.cpp void Cocos2dRenderer::nativeRedeemFailed() { //c++ code CCLog("nativeRedeemFailed"); } void Cocos2dRenderer::nativeRedeemSuccess(Platform::String^ code) { //c++ code CCLog("nativeRedeemSuccess code=%s",cocos2d::WP8Tran::pstos(code).c_str()); } ****************************************************************************
3、通常c#是用的字符串类型是Platform::String^,需要转换为std::string。以下的方法可以任意直接转化,是不是很方便呢
**************************************************************************** NS_CC_BEGIN class CC_DLL WP8Tran { public: static std::string tranChina(const char * str); static Platform::String^ tranChinatops(std::string str); static std::wstring stows(std::string s); static Platform::String^ stops(std::string s); static std::string wstos(std::wstring ws); static std::string pstos(Platform::String^ ps); }; NS_CC_END **************************************************************************** NS_CC_BEGIN #define MAX_LEN (16*1024 + 1) std::string WP8Tran::tranChina(const char * pszFormat) { char szBuf[MAX_LEN]; strcpy(szBuf,pszFormat); WCHAR wszBuf[MAX_LEN] = {0}; MultiByteToWideChar(CP_UTF8, 0, szBuf, -1, wszBuf, sizeof(wszBuf)); OutputDebugStringW(wszBuf); OutputDebugStringW(L"\n"); WideCharToMultiByte(CP_ACP, 0, wszBuf, sizeof(wszBuf), szBuf, sizeof(szBuf), NULL, FALSE); return szBuf; } Platform::String^ tranChinatops(std::string str) { //return ref new Platform::String(cocos2d::WP8Tran::stows(cocos2d::WP8Tran::tranChina(str.c_str())).c_str()); return WP8Tran::stops(WP8Tran::tranChina(str.c_str())); } std::wstring WP8Tran::stows(std::string str) { setlocale(LC_ALL, "chs"); const char* _Source = str.c_str(); size_t _Dsize = str.size() + 1; wchar_t *_Dest = new wchar_t[_Dsize]; wmemset(_Dest, 0, _Dsize); mbstowcs(_Dest,_Source,_Dsize); std::wstring result = _Dest; delete []_Dest; setlocale(LC_ALL, "C"); return result; } Platform::String^ WP8Tran::stops(std::string s) { return ref new Platform::String(stows(s).c_str()); } std::string WP8Tran::wstos(std::wstring ws) { std::string s; s.assign(ws.begin(), ws.end()); return s; } std::string WP8Tran::pstos(Platform::String^ ps) { return wstos(std::wstring(ps->Data())); } NS_CC_END ****************************************************************************
4、我把WP8DataManager全部贴出来,方便在代码中直接使用,你可以直接引用到项目的根目录,如图。
WP8DataManager.h
#ifndef __WP8DataManager_H__ #define __WP8DataManager_H__ #include "cocos2d.h" namespace PhoneDirect3DXamlAppComponent { public delegate Platform::String^ GetUniqueIDDelegate(); public delegate void ToastWP8Delegate(Platform::String^ msg); public ref class WP8DataManager sealed { public: WP8DataManager(void) { } ///DeviceInfo void SetGetUniqueIDDelegate(GetUniqueIDDelegate^ del) { m_getUniqueIDDelegate = del; } Platform::String^ GetUniqueID() { if(m_getUniqueIDDelegate) { return m_getUniqueIDDelegate->Invoke(); } return ""; } void SetToastWP8Delegate(ToastWP8Delegate^ del) { m_toastWP8Delegate = del; } void ToastWP8(Platform::String^ msg) { if(m_toastWP8Delegate) { m_toastWP8Delegate->Invoke(msg); } } ///DeviceInfo end private: property static GetUniqueIDDelegate^ m_getUniqueIDDelegate; property static ToastWP8Delegate^ m_toastWP8Delegate; }; } NS_CC_BEGIN class CC_DLL WP8Tran { public: static std::string tranChina(const char * str); static Platform::String^ tranChinatops(std::string str); static std::wstring stows(std::string s); static Platform::String^ stops(std::string s); static std::string wstos(std::wstring ws); static std::string pstos(Platform::String^ ps); }; NS_CC_END class WP8DataHelper { public: WP8DataHelper(); virtual ~WP8DataHelper(); static PhoneDirect3DXamlAppComponent::WP8DataManager^ sharedWP8DataManager(); static void purgeWP8Data(); }; #endif // __WP8DataManager_H__
WP8DataManager.cpp
#include "WP8DataManager.h" NS_CC_BEGIN #define MAX_LEN (16*1024 + 1) std::string WP8Tran::tranChina(const char * pszFormat) { char szBuf[MAX_LEN]; strcpy(szBuf,pszFormat); WCHAR wszBuf[MAX_LEN] = {0}; MultiByteToWideChar(CP_UTF8, 0, szBuf, -1, wszBuf, sizeof(wszBuf)); OutputDebugStringW(wszBuf); OutputDebugStringW(L"\n"); WideCharToMultiByte(CP_ACP, 0, wszBuf, sizeof(wszBuf), szBuf, sizeof(szBuf), NULL, FALSE); return szBuf; } Platform::String^ tranChinatops(std::string str) { //return ref new Platform::String(cocos2d::WP8Tran::stows(cocos2d::WP8Tran::tranChina(str.c_str())).c_str()); return WP8Tran::stops(WP8Tran::tranChina(str.c_str())); } std::wstring WP8Tran::stows(std::string str) { setlocale(LC_ALL, "chs"); const char* _Source = str.c_str(); size_t _Dsize = str.size() + 1; wchar_t *_Dest = new wchar_t[_Dsize]; wmemset(_Dest, 0, _Dsize); mbstowcs(_Dest,_Source,_Dsize); std::wstring result = _Dest; delete []_Dest; setlocale(LC_ALL, "C"); return result; } Platform::String^ WP8Tran::stops(std::string s) { return ref new Platform::String(stows(s).c_str()); } std::string WP8Tran::wstos(std::wstring ws) { std::string s; s.assign(ws.begin(), ws.end()); return s; } std::string WP8Tran::pstos(Platform::String^ ps) { return wstos(std::wstring(ps->Data())); } NS_CC_END static PhoneDirect3DXamlAppComponent::WP8DataManager^ m_wp8dataManager = ref new PhoneDirect3DXamlAppComponent::WP8DataManager(); WP8DataHelper::WP8DataHelper() { } WP8DataHelper:: ~WP8DataHelper() { } PhoneDirect3DXamlAppComponent::WP8DataManager^ WP8DataHelper::sharedWP8DataManager() { return m_wp8dataManager; } void WP8DataHelper::purgeWP8Data() { //delete m_wp8dataManager; }
5、下一篇会讲一下常见的错误。
github地址:https://github.com/eoeuou/wp8-xaml欢迎来喷