设为首页 收藏本站
查看: 1226|回复: 0

[经验分享] 如玫瑰一般的PHP与C#混合编程

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2015-8-23 15:20:32 | 显示全部楼层 |阅读模式
  故事背景是这样的,有一套项目,服务器端是用C#写的,为了完成某种事情,它需要使用到一个组件,这个组件很小但很重要,很不巧的是,这个这个组件是用PHP语言写的,如果为了使用这个组件而专门搭建一个PHP的环境显得有点高射炮打蚊子(况且还有其他不可预见的阻力)。或许有读者会提出“抗议”:不是PHP写的么,直接看源码翻译出一份C#版的不就行了?然而事实并不如想象的美好,总之就是短期内无法这么做了。
  如今的C#已经非常强大了,它除了可以做我们普通的站点开发、桌面开发和原生的Windows Phone、应用商店开发,还可以做其他诸如IOS、安卓开发;也通过用CLR来托起一个JVM(这里指IKVM.NET)来跑Java应用程序,当然也可以通过把PHP编译成IL来跑PHP的网站程序了。
  本篇中,我们就如何进行PHP与C#混合编程作如下讨论:
  (1)、PHP与C#的胶水:“Phalanger”
  (2)、牛刀小试跑跑PHP
  (3)、如何添加PHP类库
  (4)、C#与PHP混合互调
  (5)、美丽如玫瑰,采摘须谨慎
  本文中的示例代码请点击这里进行下载。

  1、什么是Phalanger
  什么事Phalanger,最简单的概括就是,它能够把PHP编译成DLL供我们C#调用。
  Phalanger的官网是:http://www.php-compiler.net/
  我们要做混合编程,首先得先从官网那里下载一个安装包。
DSC0000.jpg
  下载下来之后,打开压缩包,双击Setup开始安装。
DSC0001.jpg
  把这些都给安装了,前面两个必装,最后一个是模板文件,不想装就不装,已经安装的话它会写着“Already installed”。由图中,我们可以得知一个信息,那就是它只支持Framework 4.0。
  把上面的东西安装好之后,我们需要的“胶水”就得到了。
  
  2、在.NET里面跑一个php
  嗯,phpinfo(),我没有猜出,这个函数应该是各位读者们第一个敲的,也是搭建完PHP环境之后必敲写的一个函数。我们也牛刀小试一番,试试执行这个函数。
  我们先创建一个空的WebApplication
DSC0002.jpg
  然后添加一个PHP文件,由于我们没有直接的PHP文件添加,所以我们随便添加了一个内容少一点的文件,然后改它的后缀为php并删光里面的代码。
DSC0003.jpg
  写上我们的代码(还带有智能提示,先进!!!):
DSC0004.jpg
  然后按下“F5”
DSC0005.jpg 然后就奇迹般的出现了我们想要的页面。
  
  3、添加PHP的类库
  事实上,即使我们是写原生的PHP,我们都需要使用到大量的PHP库,譬如MySQL库、GD库、CURL库等。在这里当然也不例外,我们也需要使用那些库。不过在这里,我们所使用的库并不是PHP/ext中的那些库,而是Phalanger给我们准备好的库,它们随着Phalanger的安装一同安装到我们的电脑当中,有兴趣的读者可以翻开GAC目录,里面会多了很多php打头的文件夹,那些就是与Phalanger相关的库了。
DSC0006.jpg
  需要使用哪个库,就自行的在WebConfig的phpNet节点下添加,譬如我需要用MySQL的库,则在WebConfig这样配置


DSC0007.gif DSC0008.gif


<?xml version="1.0" encoding="utf-8"?>
<!--
有关如何配置 ASP.NET 应用程序的详细消息,请访问
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<phpNet>
<classLibrary>
<add assembly="PhpNetMySql, Version=3.0.0.0, Culture=neutral, PublicKeyToken=2771987119c16a03" section="mysql"/>
</classLibrary>
</phpNet>
</configuration>
Web.Config  这里注意一点,MYSQL的扩展库请使用CodePlex上的,而非自带的,自带的版本链接高板MYSQL可能会遇到问题(地址如下:http://phalangermysql.codeplex.com/releases/view/103022)
  这里还有另外一点需要注意,CodePlex上的扩展下载下来之后是这样的。
DSC0009.jpg
  MySql的库命名有问题,正确的应该是“MySql.Data.dll”,各位读者请留意。
  然后就是写下我们读取数据库信息的代码:





<?php
/***** 判断库是否被加载 *****/
$extensionName="mysql";
if(!extension_loaded($extensionName)){
echo $extensionName.'没有被加载进来';
exit;
}
/**** 操作mysql ****/
$host="192.168.70.128";
$name="root";
$pwd="root";
$conn=mysql_connect($host,$name,$pwd) or die("mysql数据库连接失败");
mysql_select_db("phalangerdb",$conn)or die("无法选择数据库");
mysql_query("set names utf8");
$sqlstr="select * from person";
$result = mysql_query($sqlstr);
echo '<pre>';
while($row=mysql_fetch_row($result)){
print_r($row);
}
echo '</pre>';
mysql_free_result($result);
mysql_close($conn);
mysqlextension.php  然后运行并查看结果:
DSC00010.jpg
  它成功的读取到我们数据库的东西并输出到页面中。
  
  4、C#与PHP互调
  既然是混合编程,如果没有两种语言之间的相互调用那又如何能够称得上混合编程呢?本节中,我们主要分两个部分,其一就是PHP调C#函数,其二就是C#掉PHP函数。
  PHP调用C#,Phalanger官网中主要的范例均是此,这里就不作讲解了,有需要的读者可移步到Phalanger官网中看里面的Blog。本文中讲解的是使用概率更高同时也是官网中比较缺乏资料的C#调用PHP的函数。
  首先我们先创建一个PHP的函数:





<?php
function Sum($a,$b){
return $a+$b;
}
function SayHello(){
return 'Hello,我是小蝶惊鸿';
}
Fun.php  然后新建一个WebForm页面程序,并在CodeBehind中调用它(这里是简单加法例子):





namespace PhalangerDemo.demo3
{
using System;
public partial class WebForm1 : System.Web.UI.Page
{
private PHP.Core.ScriptContext phpContext;
public WebForm1()
{
phpContext = PHP.Core.ScriptContext.CurrentContext;
phpContext.Include("Fun.php", true);
}
protected void Page_Load(object sender, EventArgs e)
{
var context = phpContext.Call("SayHello", new object[] { }).ToString();
Response.Write(context.StartsWith("&") ? context.Substring(1) : context);
}
protected void btnAdd_Click(object sender, EventArgs e)
{
var num1 = txtNum1.Text as object;
var num2 = txtNum2.Text as object;
var result = phpContext.Call("Sum", new object[] { num1, num2 }).ToString();
txtRes.Text = result.StartsWith("&") ? result.Substring(1) : result;
}
}
}
View Code  然后再页面中运行看看,Cool:
DSC00011.jpg
  这里,我要对CodeBehind(C#)部分的代码进行下讲解,它的原理大概如下:
  (1)、先获取PHP的上下文对象PHPContext
  (2)、然后往PHPContext中require_once我们写的“Fun.php”
  (3)、通过Call方法,第一个参数传入方法名,第二个参数传入Object数组类型的参数。调用PHP中的函数
  (4)、在被调用的PHP函数执行完成之后,将它的返回接收回来。并过滤开头的“&”字符。
  至于更深入的,譬如如何New一个PHP的Class之类的,我没有进行深入的研究,所以这里就不作描述,有兴趣的读者可以自行深入研究,同时也欢迎有此经验的读者进行分享。
  
  5、这美丽又丑陋的Phalanger
  在前面的几章中,Phalanger的表现是如此的美丽优秀,它好比一朵玫瑰,看起来是那么的鲜艳,闻起来是那么的幽香,但是当你想采摘它的时候,手中拿着的确是幽艳玫瑰之下的荆棘。也只有你划破伤口流着血的时候,你才感觉到原来采摘这朵玫瑰是那么的痛。
  我把开篇时的故事继续说完,到了这一步,读者们大概也可以猜到是个什么情况了,没错,我的尝试失败了,这个PHP的组件无法正常的运行。
  下面,我给各位读者分享两个这个组件所遇到致命性伤痕:
  (1)、if中对byte的真假识别不一致。
  同样是读取一个文件,通过if(byte[])来判断这个文件是否为空,原生的PHP中可以根据传入的byte[]是否为null来决定true/false,而Phalanger则无论如何一直返回false。
  (2)、同样的PHP内置函数,执行的效果却不一致。
  这里的所说的函数运行效果不一致并不是说效果完全的不一致,普通的使用还是没有问题的(正如我刚才读取mysql那样),而是有极少数的函数在特殊的条件下运行后得出的结果在原生PHP与Phalanger中是不一样的。

  当然了,一百个读者有一百个海姆莱特,萝卜青菜各有所爱,Phalanger到底值不值得使用,应该怎么使用,还是全凭各位读者自己博弈了。
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-103064-1-1.html 上篇帖子: php面向对象(OOP)编程完全教程 下篇帖子: 25+开源的在线购物软件(PHP, JavaScript 和 ASP.Net)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表