可運行於Windows 10 UWP的Python直譯器
Python具有豐富的功能庫,運行於多種平臺,可移植性好,使用簡單,雖然python主要運行於桌面系統,但通過對python程式碼的部分修改,已經將python直譯器成功編譯到windows 10 uwp平臺,使得在UWP應用中可以使用python指令碼。由於windows 10的限制,一些python擴充套件庫無法使用,這些擴充套件庫主要涉及到程序和管道相關的功能,對應的庫有:_winapiasyncio _overlapped_ctypes _multiprocessing _msi Subprocess。
這裡是一個運行於windows 10的python直譯器的例子,由於主要是為了說明如何初始化
1.建立工程
開啟vs2015,建立一個c# universal工程,如下圖:
新增引用,Star_csharp和libstarcore
新增python相關的庫和檔案,libstar_python34.pyd,python34.dll,python3.4.zip。python3.4.zip為python的擴充套件庫,可以根據實際需要裁剪。
設定python檔案的屬性
\
2. 初始化CLE和python
例子基於CLE開發,首先需要初始化CLE,初始化CLE有兩種方式,直接在介面執行緒中初始化,此時CLE運行於介面執行緒,python直譯器同樣運行於介面執行緒,python程式碼也在介面執行緒中執行;另外一種方式是建立一個獨立的執行緒初始化CLE,python直譯器執行在初始化CLE的執行緒中,這種方式的好處是python指令碼的執行不會影響介面重新整理,但是從介面執行緒呼叫CLE相關的函式,或者執行python指令碼,需要進行加鎖操作,此外該執行緒需要維護CLE的訊息迴圈。
2.1 在介面執行緒中初始化CLE和python
StarCoreFactoryInit.Init(this); StarCoreFactory starcore = StarCoreFactory.GetFactory(); StarServiceClass Service = (StarServiceClass)starcore._InitSimple("test", "123", 0, 0, null); SrvGroup = (StarSrvGroupClass)Service._Get("_ServiceGroup"); bool Result = SrvGroup._InitRaw("python34", Service); StarObjectClass python = Service._ImportRawContext("python", "", false, "");
2.2 在獨立執行緒中初始化CLE和python
使用BackgroundWorker建立執行緒,線上程中初始化CLE和python
backroungServer = new BackgroundWorker();
backroungServer.DoWork += new DoWorkEventHandler(backroungServer_DoWork);
backroungServer.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backroungServer_Complete);
backroungServer.ProgressChanged += OnServerProgressChanged;
backroungServer.WorkerReportsProgress = true;
backroungServer.RunWorkerAsync();
private void backroungServer_DoWork(object sender, DoWorkEventArgs e)
{
StarCoreFactoryInit.Init(this);
StarCoreFactory starcore = StarCoreFactory.GetFactory();
StarServiceClass Service = (StarServiceClass)starcore._InitSimple("test", "123", 0, 0, null);
SrvGroup = (StarSrvGroupClass)Service._Get("_ServiceGroup");
bool Result = SrvGroup._InitRaw("python34", Service);
StarObjectClass python = Service._ImportRawContext("python", "", false, "");
//---enter message loop
while (true)
{
while (starcore._SRPDispatch(false) == true) ;
starcore._SRPUnLock();
Task.Delay(10).Wait();
starcore._SRPLock();
}
}
private void OnServerProgressChanged(object sender, ProgressChangedEventArgs e)
{
}
private void backroungServer_Complete(object sender, RunWorkerCompletedEventArgs e)
{
}
3. 捕獲python指令碼的輸出
為了捕獲python指令碼的輸出結果,需要註冊CLE的回撥函式,實現StarMsgCallBackInterface介面,在回撥函式中,將輸出結果顯示到文字框中
starcore._RegMsgCallBack_P(new StarMsgCallBackInterface(delegate (int ServiceGroupID, int uMes, object wParam, object lParam)
{
if (uMes == starcore._Getint("MSG_DISPMSG") || uMes == starcore._Getint("MSG_DISPLUAMSG"))
{
textBlock1.Text = textBlock1.Text + "\n" + (string)wParam;
}
return null;
}));
4. 執行python指令碼
4.1編譯不執行
可以只編譯指令碼,不執行,此時檢查指令碼中的語法錯誤。編譯指令碼需要呼叫CLE的函式_PreCompile。該函式返回一個object[]陣列,如果object[0]是true,則成功編譯;如果為false, 並且object[1]的長度為0,表示輸入指令碼不完整;否則object[1]返回編譯錯誤。
private void button_Click(object sender, RoutedEventArgs e)
{
string script = textBox.Text;
if (script.Length == 0)
return;
#if CLETHREAD
starcore._SRPLock();
#endif
object[] result = SrvGroup._PreCompile("python", script+"\n");
#if CLETHREAD
starcore._SRPUnLock();
#endif
if ((bool)result[0] == true)
textBlock1.Text = "success";
else
{
if (((string)result[1]).Length == 0)
textBlock1.Text = "More Input";
else
textBlock1.Text = (string)result[1];
}
}
4.2直接執行指令碼
呼叫CLE的函式_RunScript執行python指令碼。指令碼的輸出會被之前設定的回撥函式捕獲,顯示到輸出視窗中。
private void button1_Click(object sender, RoutedEventArgs e)
{
textBlock1.Text = "";
string script = textBox.Text;
if (script.Length == 0)
return;
#if CLETHREAD
starcore._SRPLock();
#endif
Service._RunScript("python", script + "\n", "", "");
#if CLETHREAD
starcore._SRPUnLock();
#endif
}
5.支援arm的版本
如果需要執行在window 10 mobile裝置上,需要編譯arm的版本,此時要將引用,python相關的檔案替換為arm對應的檔案。
首先刪除工程中的上述檔案,然後再新增,步驟參考步驟1,只不過在選擇檔案的時候,選取arm目錄下的檔案
6.結束語
本例子實現了一個可運行於windows 10 uwp平臺的python直譯器,程式碼非常簡單。可以參考本文中的方法,在UWP應用中使用python指令碼語言。編譯執行本文中的例子需要CLE(),下載之後解壓,與例子放在統一目錄,如下: