程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> 把PHP作為C#程序的腳本語言(翻譯)

把PHP作為C#程序的腳本語言(翻譯)

編輯:關於PHP編程

原文: http://dotnet.dzone.com/articles/php-scripting-language-c
 
當我們打算創建一個.net程序時(包括桌面程序或者Web應用程序),如果能使用其他語言來擴展這個.net程序的功能的話那肯定會相當有實用價值。
 
比如某些用戶可以寫一個簡單腳本來設置這個程序的一些設定,或者在程序中修改數據是如何持久化保存的,或者為這個.net程序寫一個簡單的插件。在這篇文章,我們來看看如何讓php作為.net程序的腳本語言
顯然這樣做有很多的好處:
1,很多程序員都會寫一些基本的PHP代碼,甚至一個初級程序員都能為你的應用寫一個簡單的PHP腳本代碼
2, PHP是非常容易使用的,網絡上已經有了一大堆現成的php代碼片段可以拿來復制後直接使用
3,歸功於Phalanger庫( http://phalanger.codeplex.com/), PHP代碼能夠很容易地獲取任何.net庫以及調用幾乎所有.net程序提供的服務
 
上面描述的場景僅僅只是使用Phalanger from C#(或者其他編程語言)在運行時生成PHP代碼的一小部分案例,打個比方,你能想象一下一個web網絡架構使用C#來寫域名模塊然後使用PHP去搭建用戶接口會是什麼樣子. 所以本文將展示如何在C#的程序中運行PHP代碼,與怎麼使用全局變量作為參數傳遞到PHP代碼,以及如何讀取標准.net流。
 
Phalanger 是一個將PHP腳本編譯成.net字節碼的編譯器,它本身就被設計用來允許無縫地讓.net與其他語言進行雙向的互操作性。
這就意味著你能在php代碼中調用.net方法以及使用.net的類( http://wiki.phpcompiler.net/.NET_interoperability),同時你也能在C#或者F#中調用php的方法以及使用php的類.( http://wiki.phpcompiler.net/Code_Samples/Standard_mode_interoperability)
同時本文展示了另外一種使用Phalanger的方式:通過.net程序來運行php代碼.尤其當被運行的代碼是動態獲取的或者無法被預編譯為程序集時(例如當代碼是後來被用戶所寫的這種情況).當運行的的php代碼沒有任何改變時,一般你應該使用預編譯的腳本庫( http://wiki.phpcompiler.net/Code_Samples/Standard_mode_interoperability),這樣能夠得到更高的效率因為在運行時它們不會參與編譯。
 
配置
 
在ASP.NET 4.0 C#的網站程序中我已經測試過這個技術了,當然,在.net控制台程序或者winforms這樣的桌面應用程序中也是可行的。但要記住你的.net程序必須是使用.net 4.0(full profile)作為目標.net框架,以及必須引用至少一個Phalanger的程序集:“PhpNetCore, Version=2.1.0.0, Culture=neutral, PublicKeyToken=0A8E8C4C76728C71". Phalanger必須在你的應用程序中正確配置。雖然它一樣可以被手動配置(http://www.php-compiler.net/blog/2011/installation-free-phalanger-web),但最簡單的方式就是使用安裝器了。
 
源碼
 
不可思議的是運行PHP代碼的核心就是PHP.Core.DynamicCode.Eval這個方法, 它在PhpNetCore.dll程序集中,唯一有些麻煩的可能就是方法所需的大量參數了。首先我們需要一個可用的PHP.Core.ScriptContext實例, 這就是Phalanger的運行php代碼的執行實例。你能從當前線程上獲取一個這樣的實例.特別注意PHP不是多線程的,所以ScriptContext只是僅僅與一個線程緊密關聯
 
1
var context = PHP.Core.ScriptContext.CurrentContext;
然後我們將設置ScriptContext的輸出方式,這樣PHP腳本才能轉換出我們所需要的流。這裡我們將設置兩個輸出方式- 字節流以及文本流。注意在最後你必須銷毀這些流,以至於所有的數據將會被正確的刷新
 
1
context.OutputStream = output;
2
using (context.Output = new System.IO.StreamWriter(output)) {
我們也能在ScriptContext中設置全局變量,這樣我們也能很方便的傳輸一些參數到運行的PHP代碼中。
1
Operators.SetVariable(context, null, "X", "Hello World!");
最終我們將使用的Eval方法來運行PHP代碼. 而這個方法實際上被Phalanger內部用來處理PHP的eval() 表達式.所以這就是為什麼這個方法有如此多參數的原因。
01
// evaluate our code:
02
return DynamicCode.Eval(
03
    code,
04
    false,/*phalanger internal stuff*/
05
    context,
06
    null,/*local variables*/
07
    null,/*reference to "$this"*/
08
    null,/*current class context*/
09
    "Default.aspx.cs",/*file name, used for debug and cache key*/
10
    1,1,/*position in the file used for debug and cache key*/
11
    -1,/*something internal*/
12
    null/*current namespace, used in CLR mode*/
13
);
如果運行代碼表現得和全局php代碼一樣時,大部分參數看上去就沒什麼特別之處了。最重要的參數就是code.該參數是一個包含你的php代碼的字符串。Phalanger將先轉譯然後再編譯這段代碼。轉換出的.net字節碼被將被作為臨時程序集被存儲在內存中(我們也稱它為瞬時程序集)
 
。注意整個轉譯以及編譯的過程很快,因為瞬時程序集也會被緩存起來加速的運行相同PHP代碼。
 
如你所見,你也能在參數file name以及postion中提供文件名以及文件所在位置;所以當你調試代碼然後單步調試進入表達式時,它將會剛好跳到position參數指定的位置。
注意被緩存的瞬時程序集是否被更新將依賴於ScriptContext前面執行的PHP代碼(比如定義好的類以及方法),只有前後兩次生成的PHP代碼一致時,瞬時程序集才能被緩存下來。這就是為什麼Eval方法中的參數code,file name以及position與前面的的匹配時才能緩存後被重用。
 
那麼我們要記住,當隨後要運行更多的PHP代碼片段時你應該首先考慮這個問題。
最後如果你打算在web應用程序中使用Phalanger時,你應該首先就初始化PHP.Core.RequestContext, 然後在php腳本結束時銷毀它。
1
using (var request_context = RequestContext.Initialize(
2
                 ApplicationContext.Default,
3
                 HttpContext.Current))
4
{ /* all the stuff above */ }
總結:
 
 總共就是這些。 因為後面執行的的PHP代碼中也包含了已經定義好的PHP方法,變量以及類,所以你也能在.net代碼中使用它們。
.net應用程序功能的語言。你也能用這個技術去創建一個使用c#建立域名模塊和PHP搭建用戶接口的web應用程序。
 
如果你對這個感興趣,希望得到更多的信息,你可以查閱Standard_mode_interoperability的最新文章(http://wiki.phpcompiler.net/Code_Samples/Standard_mode_interoperability)
作者 junwong的博客

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved