Windows Phone 8 學習志(探索問題一:如何簡單利用Windows Phone Runtime Component項目類型實現C#和C++交互)


一、前言:

  沒想到上一篇文章已經是一年前寫的了,一直在寫Windows Phone的程序,比較完整的例如LR Maps地圖系列還有一些公司開發的項目,不過現在因為百度地圖出了官方版本,在地圖方面我也算是正式退役了,其間覺得能寫出來分享交流的的確不是很多,不過主要自己還是懶了點,而且覺得水平有點不濟。最近開始研究Windows Phone 8 Preview SDK,早先就有泄露版的SDK流出,那時候就安裝並且看了看文檔和新功能,最近官方正式Window Phone 8 Preview SDK也申請使用成功,又重新安裝了遍。當初申請的時候也沒仔細閱讀隱私保密條款,不過想必肯定有,不過本篇文章只是談自己在Windows Phone 8 SDK環境下最近研究C#和C++交互方面的內容,所以與隱私保密條款應該沒什么沖突。SDK文檔里說這方面的東西真不多,幾筆就帶過了,還是后來查WIN8的MSDN文檔才覺得靠譜,因為自己對C++的不熟悉,輾轉許久才最終完成了簡單任務,現在寫這篇文章,希望大家不要像我一樣走一些彎路。

二、簡單介紹

  問:為什么要用C++代碼,如何簡單使用?

  答:很多時候因為解決某些問題用的是C++移植到C#的代碼的話,那效率是大打折扣的,而能夠使用C++代碼也就說明能用更多的開源C++代碼,還不用手動移植到C#,這是非常方便的。

  WP8中新建項目的類型中新增了C++類型的項目,如下圖:

  前兩個是Direct3D相關的東西,和我們今天討論的話題沒什么聯系。最后兩個大家應該很熟悉,動態鏈接庫和靜態鏈接庫。

  今天着重介紹的就是Windows Phone Runtime Component,就我現在比較粗俗的理解,因為畢竟Windows Phone Runtime Component項目類型是C++項目,那么必然可以在Windows Phone Runtime Component項目里使用C++代碼,但從另外個角度想那為什么不是直接可以在Windows Phone項目中直接調用動態鏈接庫呢?因此我把Windows Phone Runtime Component理解成一個中間層,一個C#和C++交互的中間層。

  或許這時候有人就說了:既然能用C++代碼了,那標題的問題完全迎刃而解,還有什么需要探索的呢?

  那就讓我們一步步從簡單的調用開始實現以下內容,前兩部分內容比較簡單,其他地方也能搜到,所以就簡略介紹,自己看最后附的代碼:

  (1)簡單調用C++方法

  (2)簡單調用DLL

  (3)簡單調用帶指針參數的C++方法

二、實現過程

(1)簡單調用C++方法

  1、新建Windows Phone Runtime Component項目,在新生成的.h文件中加入代碼:

  int Add(int x, int y)
  {
    return x + y;
  }

  2、在主程序中項目中加入之前的Windows Phone Runtime Component項目引用,然后直接new一個新實例就能直接調用方法了。

(2)簡單調用DLL

  問:為什么要調用DLL不直接移植到Windows Phone Runtime Component項目呢?

  答:如果有源代碼的話,建議直接把源代碼復制到Windows Phone Runtime Component項目中,然后引用后直接進行調用,效率上可以更快一點,如果是.c文件名后綴記得改成.cpp。

  DLL調用分為靜態調用和動態調用,前者需要.lib和.h文件,而后者只需要.dll文件不過需要在引用地方申明具體方法參數。

  因為我自己對這方面以前沒怎么用過,所以會折騰一會會,大家有經驗的可以略過這邊,沒經驗的可以去這個地址看看,最后示例代碼會加入動態調用的實現。

(3)簡單調用帶指針參數的C++方法

  其實這個才是困惑我比較久和我想和大家交流的問題,因為前面都只是傳遞簡單的int值,而int對於C#和C++基本沒什么區別,但是要是換成C++的unsigned char*的話,C#會主動為我們把方法傳入參數改成byte[]么?

  答案是否定的,如果是這樣一個C++方法int Cal(unsigned char* parameter1, unsigned char* parameter2),C#會識別為int Call(out byte parameter1,out byte parameter1),這不是讓C#傳個指針進來么?但是我們又不能用unsafe方法來獲取指針進行傳遞。那我把unsigned char*改成byte[]?當然也不行啦。

  我當初就在這里百思不得其解,還看了Marshal和IntPtr的使用,還真妄想在C#這層把問題解決。后來直到靜下心來看了WIN8 MSDN上關於Visual C++ Language Reference (C++/CX)才發現了方法。這也是我覺得Windows Phone Runtime Component作為中間層的原因,數據的封送是由C#-》C++/CX-》C++傳遞過去的。這樣子解決剛才的問題一下子就簡單了,只需找出對應的數據類型就可以了。

  C++:int Cal(const unsigned char* parameter1, unsigned char* parameter2)

  Runtime:int Cal(const Array<unsigned char>^ parameter1, Array<unsigned char>^* parameter2)

  C#:int Cal(byte[] parameter1,out byte[] parameter2)

  其中Runtime拿到Array<unsigned char>還需轉換成unsigned char*,不過非常簡單,因為Array有個Data就是unsigned char*,而當返回結果的時候,unsigned char*還得轉回Array<unsigned char>,也不用擔心,直接ref new Array<unsigned char>(unsigned char* parameter1,parameter1Len),Array的初始化方法就有直接使用unsigned char*的。

     當然這里我主要處理的是C#的數組,但如果是一個其他指針需要通過Runtime傳入修改,那其實只要用public ref class的類來封裝就可以了。

三、總結

  摸索一些自己不擅長領域的知識和問題的時候,可能常常搜索不到一些有用的結果,原因很大程度是因為那些知識比較新,用得比較少,這時候還是得從根源上找解決方案,把基礎部分研究一遍才行,否則就可能和我一樣,繞了一大圈,為了找答案而找答案,最后又回到了原點,不過還好終於把問題解決了,也學到了不少東西。拋磚引玉,聊以自勉了,如果大家有更好的解決辦法,也希望能夠一起討論,畢竟我也只是一家之言。

源代碼下載


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM