1. 程式人生 > >可運行於Windows 10 UWP的Python直譯器

可運行於Windows 10 UWP的Python直譯器

Python具有豐富的功能庫,運行於多種平臺,可移植性好,使用簡單,雖然python主要運行於桌面系統,但通過對python程式碼的部分修改,已經將python直譯器成功編譯到windows 10 uwp平臺,使得在UWP應用中可以使用python指令碼。由於windows 10的限制,一些python擴充套件庫無法使用,這些擴充套件庫主要涉及到程序和管道相關的功能,對應的庫有:_winapiasyncio _overlapped_ctypes _multiprocessing _msi Subprocess

這裡是一個運行於windows 10python直譯器的例子,由於主要是為了說明如何初始化

python直譯器,執行python指令碼,例子中的介面比較簡單,一個輸入欄用於輸入python腳,一個輸出欄用於顯示執行的結果。

1.建立工程

    開啟vs2015,建立一個c# universal工程,如下圖:

   

    新增引用,Star_csharplibstarcore

   

    新增python相關的庫和檔案,libstar_python34.pydpython34.dllpython3.4.zippython3.4.zippython的擴充套件庫,可以根據實際需要裁剪。

   

    設定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),下載之後解壓,與例子放在統一目錄,如下: